Format code style.

This commit is contained in:
zhangzihao 2021-04-26 15:06:47 +08:00
parent a70be3f810
commit 422c73fd1e
141 changed files with 11473 additions and 12282 deletions

View File

@ -24,11 +24,10 @@
static ChineseSegmentation *global_instance_chinese_segmentation = nullptr;
QMutex ChineseSegmentation::m_mutex;
ChineseSegmentation::ChineseSegmentation()
{
ChineseSegmentation::ChineseSegmentation() {
const char * const DICT_PATH = "/usr/share/ukui-search/res/dict/jieba.dict.utf8";
const char * const HMM_PATH = "/usr/share/ukui-search/res/dict/hmm_model.utf8";
const char * const USER_DICT_PATH ="/usr/share/ukui-search/res/dict/user.dict.utf8";
const char * const USER_DICT_PATH = "/usr/share/ukui-search/res/dict/user.dict.utf8";
const char * const IDF_PATH = "/usr/share/ukui-search/res/dict/idf.utf8";
const char * const STOP_WORD_PATH = "/usr/share/ukui-search/res/dict/stop_words.utf8";
@ -39,26 +38,23 @@ ChineseSegmentation::ChineseSegmentation()
STOP_WORD_PATH);
}
ChineseSegmentation::~ChineseSegmentation()
{
ChineseSegmentation::~ChineseSegmentation() {
if(m_jieba)
delete m_jieba;
m_jieba = nullptr;
}
ChineseSegmentation *ChineseSegmentation::getInstance()
{
ChineseSegmentation *ChineseSegmentation::getInstance() {
QMutexLocker locker(&m_mutex);
if (!global_instance_chinese_segmentation) {
if(!global_instance_chinese_segmentation) {
global_instance_chinese_segmentation = new ChineseSegmentation;
}
return global_instance_chinese_segmentation;
}
QVector<SKeyWord> ChineseSegmentation::callSegement(QString str)
{
QVector<SKeyWord> ChineseSegmentation::callSegement(QString str) {
std::string s;
s=str.toStdString();
s = str.toStdString();
str.squeeze();
const size_t topk = -1;
@ -76,9 +72,8 @@ QVector<SKeyWord> ChineseSegmentation::callSegement(QString str)
}
void ChineseSegmentation::convert(std::vector<cppjieba::KeywordExtractor::Word> &keywordres, QVector<SKeyWord> &kw)
{
for (auto i : keywordres){
void ChineseSegmentation::convert(std::vector<cppjieba::KeywordExtractor::Word> &keywordres, QVector<SKeyWord> &kw) {
for(auto i : keywordres) {
SKeyWord temp;
temp.word = i.word;
temp.offsets = QVector<size_t>::fromStdVector(i.offsets);

View File

@ -32,24 +32,23 @@
#include <QDebug>
#include <QMutex>
struct SKeyWord{
struct SKeyWord {
std::string word;
QVector<size_t> offsets;
double weight;
~SKeyWord(){
~SKeyWord() {
word = std::move("");
offsets.clear();
offsets.shrink_to_fit();
}
};
class CHINESESEGMENTATION_EXPORT ChineseSegmentation
{
class CHINESESEGMENTATION_EXPORT ChineseSegmentation {
public:
static ChineseSegmentation *getInstance();
~ChineseSegmentation();
QVector<SKeyWord> callSegement(QString str);
void convert(std::vector<cppjieba::KeywordExtractor::Word>& keywordres,QVector<SKeyWord>& kw);
void convert(std::vector<cppjieba::KeywordExtractor::Word>& keywordres, QVector<SKeyWord>& kw);
private:
static QMutex m_mutex;
cppjieba::Jieba *m_jieba;

View File

@ -43,252 +43,247 @@ const size_t DICT_COLUMN_NUM = 3;
const char* const UNKNOWN_TAG = "";
class DictTrie {
public:
enum UserWordWeightOption {
WordWeightMin,
WordWeightMedian,
WordWeightMax,
}; // enum UserWordWeightOption
public:
enum UserWordWeightOption {
WordWeightMin,
WordWeightMedian,
WordWeightMax,
}; // enum UserWordWeightOption
DictTrie(const string& dict_path, const string& user_dict_paths = "", UserWordWeightOption user_word_weight_opt = WordWeightMedian) {
Init(dict_path, user_dict_paths, user_word_weight_opt);
}
~DictTrie() {
delete trie_;
}
bool InsertUserWord(const string& word, const string& tag = UNKNOWN_TAG) {
DictUnit node_info;
if (!MakeNodeInfo(node_info, word, user_word_default_weight_, tag)) {
return false;
DictTrie(const string& dict_path, const string& user_dict_paths = "", UserWordWeightOption user_word_weight_opt = WordWeightMedian) {
Init(dict_path, user_dict_paths, user_word_weight_opt);
}
active_node_infos_.push_back(node_info);
trie_->InsertNode(node_info.word, &active_node_infos_.back());
return true;
}
bool InsertUserWord(const string& word,int freq, const string& tag = UNKNOWN_TAG) {
DictUnit node_info;
double weight = freq ? log(1.0 * freq / freq_sum_) : user_word_default_weight_ ;
if (!MakeNodeInfo(node_info, word, weight , tag)) {
return false;
~DictTrie() {
delete trie_;
}
active_node_infos_.push_back(node_info);
trie_->InsertNode(node_info.word, &active_node_infos_.back());
return true;
}
const DictUnit* Find(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end) const {
return trie_->Find(begin, end);
}
void Find(RuneStrArray::const_iterator begin,
RuneStrArray::const_iterator end,
vector<struct Dag>&res,
size_t max_word_len = MAX_WORD_LENGTH) const {
trie_->Find(begin, end, res, max_word_len);
}
bool Find(const string& word)
{
const DictUnit *tmp = NULL;
RuneStrArray runes;
if (!DecodeRunesInString(word, runes))
{
XLOG(ERROR) << "Decode failed.";
bool InsertUserWord(const string& word, const string& tag = UNKNOWN_TAG) {
DictUnit node_info;
if(!MakeNodeInfo(node_info, word, user_word_default_weight_, tag)) {
return false;
}
active_node_infos_.push_back(node_info);
trie_->InsertNode(node_info.word, &active_node_infos_.back());
return true;
}
tmp = Find(runes.begin(), runes.end());
if (tmp == NULL)
{
return false;
bool InsertUserWord(const string& word, int freq, const string& tag = UNKNOWN_TAG) {
DictUnit node_info;
double weight = freq ? log(1.0 * freq / freq_sum_) : user_word_default_weight_ ;
if(!MakeNodeInfo(node_info, word, weight, tag)) {
return false;
}
active_node_infos_.push_back(node_info);
trie_->InsertNode(node_info.word, &active_node_infos_.back());
return true;
}
else
{
return true;
const DictUnit* Find(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end) const {
return trie_->Find(begin, end);
}
}
bool IsUserDictSingleChineseWord(const Rune& word) const {
return IsIn(user_dict_single_chinese_word_, word);
}
void Find(RuneStrArray::const_iterator begin,
RuneStrArray::const_iterator end,
vector<struct Dag>&res,
size_t max_word_len = MAX_WORD_LENGTH) const {
trie_->Find(begin, end, res, max_word_len);
}
double GetMinWeight() const {
return min_weight_;
}
bool Find(const string& word) {
const DictUnit *tmp = NULL;
RuneStrArray runes;
if(!DecodeRunesInString(word, runes)) {
XLOG(ERROR) << "Decode failed.";
}
tmp = Find(runes.begin(), runes.end());
if(tmp == NULL) {
return false;
} else {
return true;
}
}
void InserUserDictNode(const string& line) {
vector<string> buf;
DictUnit node_info;
Split(line, buf, " ");
if(buf.size() == 1){
MakeNodeInfo(node_info,
buf[0],
user_word_default_weight_,
UNKNOWN_TAG);
} else if (buf.size() == 2) {
MakeNodeInfo(node_info,
buf[0],
user_word_default_weight_,
buf[1]);
} else if (buf.size() == 3) {
int freq = atoi(buf[1].c_str());
assert(freq_sum_ > 0.0);
double weight = log(1.0 * freq / freq_sum_);
MakeNodeInfo(node_info, buf[0], weight, buf[2]);
bool IsUserDictSingleChineseWord(const Rune& word) const {
return IsIn(user_dict_single_chinese_word_, word);
}
double GetMinWeight() const {
return min_weight_;
}
void InserUserDictNode(const string& line) {
vector<string> buf;
DictUnit node_info;
Split(line, buf, " ");
if(buf.size() == 1) {
MakeNodeInfo(node_info,
buf[0],
user_word_default_weight_,
UNKNOWN_TAG);
} else if(buf.size() == 2) {
MakeNodeInfo(node_info,
buf[0],
user_word_default_weight_,
buf[1]);
} else if(buf.size() == 3) {
int freq = atoi(buf[1].c_str());
assert(freq_sum_ > 0.0);
double weight = log(1.0 * freq / freq_sum_);
MakeNodeInfo(node_info, buf[0], weight, buf[2]);
}
static_node_infos_.push_back(node_info);
if (node_info.word.size() == 1) {
user_dict_single_chinese_word_.insert(node_info.word[0]);
if(node_info.word.size() == 1) {
user_dict_single_chinese_word_.insert(node_info.word[0]);
}
}
void LoadUserDict(const vector<string>& buf) {
for (size_t i = 0; i < buf.size(); i++) {
InserUserDictNode(buf[i]);
}
}
void LoadUserDict(const set<string>& buf) {
std::set<string>::const_iterator iter;
for (iter = buf.begin(); iter != buf.end(); iter++){
InserUserDictNode(*iter);
}
}
void LoadUserDict(const string& filePaths) {
vector<string> files = limonp::Split(filePaths, "|;");
size_t lineno = 0;
for (size_t i = 0; i < files.size(); i++) {
ifstream ifs(files[i].c_str());
XCHECK(ifs.is_open()) << "open " << files[i] << " failed";
string line;
for (; getline(ifs, line); lineno++) {
if (line.size() == 0) {
continue;
void LoadUserDict(const vector<string>& buf) {
for(size_t i = 0; i < buf.size(); i++) {
InserUserDictNode(buf[i]);
}
InserUserDictNode(line);
}
}
}
private:
void Init(const string& dict_path, const string& user_dict_paths, UserWordWeightOption user_word_weight_opt) {
LoadDict(dict_path);
freq_sum_ = CalcFreqSum(static_node_infos_);
CalculateWeight(static_node_infos_, freq_sum_);
SetStaticWordWeights(user_word_weight_opt);
if (user_dict_paths.size()) {
LoadUserDict(user_dict_paths);
}
Shrink(static_node_infos_);
CreateTrie(static_node_infos_);
}
void CreateTrie(const vector<DictUnit>& dictUnits) {
assert(dictUnits.size());
vector<Unicode> words;
vector<const DictUnit*> valuePointers;
for (size_t i = 0 ; i < dictUnits.size(); i ++) {
words.push_back(dictUnits[i].word);
valuePointers.push_back(&dictUnits[i]);
}
trie_ = new Trie(words, valuePointers);
}
bool MakeNodeInfo(DictUnit& node_info,
const string& word,
double weight,
const string& tag) {
if (!DecodeRunesInString(word, node_info.word)) {
XLOG(ERROR) << "Decode " << word << " failed.";
return false;
void LoadUserDict(const set<string>& buf) {
std::set<string>::const_iterator iter;
for(iter = buf.begin(); iter != buf.end(); iter++) {
InserUserDictNode(*iter);
}
}
node_info.weight = weight;
node_info.tag = tag;
return true;
}
void LoadDict(const string& filePath) {
ifstream ifs(filePath.c_str());
XCHECK(ifs.is_open()) << "open " << filePath << " failed.";
string line;
vector<string> buf;
void LoadUserDict(const string& filePaths) {
vector<string> files = limonp::Split(filePaths, "|;");
size_t lineno = 0;
for(size_t i = 0; i < files.size(); i++) {
ifstream ifs(files[i].c_str());
XCHECK(ifs.is_open()) << "open " << files[i] << " failed";
string line;
DictUnit node_info;
for (size_t lineno = 0; getline(ifs, line); lineno++) {
Split(line, buf, " ");
XCHECK(buf.size() == DICT_COLUMN_NUM) << "split result illegal, line:" << line;
MakeNodeInfo(node_info,
buf[0],
atof(buf[1].c_str()),
buf[2]);
static_node_infos_.push_back(node_info);
for(; getline(ifs, line); lineno++) {
if(line.size() == 0) {
continue;
}
InserUserDictNode(line);
}
}
}
}
static bool WeightCompare(const DictUnit& lhs, const DictUnit& rhs) {
return lhs.weight < rhs.weight;
}
void SetStaticWordWeights(UserWordWeightOption option) {
XCHECK(!static_node_infos_.empty());
vector<DictUnit> x = static_node_infos_;
sort(x.begin(), x.end(), WeightCompare);
min_weight_ = x[0].weight;
max_weight_ = x[x.size() - 1].weight;
median_weight_ = x[x.size() / 2].weight;
switch (option) {
case WordWeightMin:
user_word_default_weight_ = min_weight_;
break;
case WordWeightMedian:
user_word_default_weight_ = median_weight_;
break;
default:
user_word_default_weight_ = max_weight_;
break;
private:
void Init(const string& dict_path, const string& user_dict_paths, UserWordWeightOption user_word_weight_opt) {
LoadDict(dict_path);
freq_sum_ = CalcFreqSum(static_node_infos_);
CalculateWeight(static_node_infos_, freq_sum_);
SetStaticWordWeights(user_word_weight_opt);
if(user_dict_paths.size()) {
LoadUserDict(user_dict_paths);
}
Shrink(static_node_infos_);
CreateTrie(static_node_infos_);
}
}
double CalcFreqSum(const vector<DictUnit>& node_infos) const {
double sum = 0.0;
for (size_t i = 0; i < node_infos.size(); i++) {
sum += node_infos[i].weight;
void CreateTrie(const vector<DictUnit>& dictUnits) {
assert(dictUnits.size());
vector<Unicode> words;
vector<const DictUnit*> valuePointers;
for(size_t i = 0 ; i < dictUnits.size(); i ++) {
words.push_back(dictUnits[i].word);
valuePointers.push_back(&dictUnits[i]);
}
trie_ = new Trie(words, valuePointers);
}
return sum;
}
void CalculateWeight(vector<DictUnit>& node_infos, double sum) const {
assert(sum > 0.0);
for (size_t i = 0; i < node_infos.size(); i++) {
DictUnit& node_info = node_infos[i];
assert(node_info.weight > 0.0);
node_info.weight = log(double(node_info.weight)/sum);
bool MakeNodeInfo(DictUnit& node_info,
const string& word,
double weight,
const string& tag) {
if(!DecodeRunesInString(word, node_info.word)) {
XLOG(ERROR) << "Decode " << word << " failed.";
return false;
}
node_info.weight = weight;
node_info.tag = tag;
return true;
}
}
void Shrink(vector<DictUnit>& units) const {
vector<DictUnit>(units.begin(), units.end()).swap(units);
}
void LoadDict(const string& filePath) {
ifstream ifs(filePath.c_str());
XCHECK(ifs.is_open()) << "open " << filePath << " failed.";
string line;
vector<string> buf;
vector<DictUnit> static_node_infos_;
deque<DictUnit> active_node_infos_; // must not be vector
Trie * trie_;
DictUnit node_info;
for(size_t lineno = 0; getline(ifs, line); lineno++) {
Split(line, buf, " ");
XCHECK(buf.size() == DICT_COLUMN_NUM) << "split result illegal, line:" << line;
MakeNodeInfo(node_info,
buf[0],
atof(buf[1].c_str()),
buf[2]);
static_node_infos_.push_back(node_info);
}
}
double freq_sum_;
double min_weight_;
double max_weight_;
double median_weight_;
double user_word_default_weight_;
unordered_set<Rune> user_dict_single_chinese_word_;
static bool WeightCompare(const DictUnit& lhs, const DictUnit& rhs) {
return lhs.weight < rhs.weight;
}
void SetStaticWordWeights(UserWordWeightOption option) {
XCHECK(!static_node_infos_.empty());
vector<DictUnit> x = static_node_infos_;
sort(x.begin(), x.end(), WeightCompare);
min_weight_ = x[0].weight;
max_weight_ = x[x.size() - 1].weight;
median_weight_ = x[x.size() / 2].weight;
switch(option) {
case WordWeightMin:
user_word_default_weight_ = min_weight_;
break;
case WordWeightMedian:
user_word_default_weight_ = median_weight_;
break;
default:
user_word_default_weight_ = max_weight_;
break;
}
}
double CalcFreqSum(const vector<DictUnit>& node_infos) const {
double sum = 0.0;
for(size_t i = 0; i < node_infos.size(); i++) {
sum += node_infos[i].weight;
}
return sum;
}
void CalculateWeight(vector<DictUnit>& node_infos, double sum) const {
assert(sum > 0.0);
for(size_t i = 0; i < node_infos.size(); i++) {
DictUnit& node_info = node_infos[i];
assert(node_info.weight > 0.0);
node_info.weight = log(double(node_info.weight) / sum);
}
}
void Shrink(vector<DictUnit>& units) const {
vector<DictUnit>(units.begin(), units.end()).swap(units);
}
vector<DictUnit> static_node_infos_;
deque<DictUnit> active_node_infos_; // must not be vector
Trie * trie_;
double freq_sum_;
double min_weight_;
double max_weight_;
double median_weight_;
double user_word_default_weight_;
unordered_set<Rune> user_dict_single_chinese_word_;
};
}

View File

@ -29,82 +29,82 @@
namespace cppjieba {
class FullSegment: public SegmentBase {
public:
FullSegment(const string& dictPath) {
dictTrie_ = new DictTrie(dictPath);
isNeedDestroy_ = true;
}
FullSegment(const DictTrie* dictTrie)
: dictTrie_(dictTrie), isNeedDestroy_(false) {
assert(dictTrie_);
}
~FullSegment() {
if (isNeedDestroy_) {
delete dictTrie_;
public:
FullSegment(const string& dictPath) {
dictTrie_ = new DictTrie(dictPath);
isNeedDestroy_ = true;
}
}
void Cut(const string& sentence,
vector<string>& words) const {
vector<Word> tmp;
Cut(sentence, tmp);
GetStringsFromWords(tmp, words);
}
void Cut(const string& sentence,
vector<Word>& words) const {
PreFilter pre_filter(symbols_, sentence);
PreFilter::Range range;
vector<WordRange> wrs;
wrs.reserve(sentence.size()/2);
while (pre_filter.HasNext()) {
range = pre_filter.Next();
Cut(range.begin, range.end, wrs);
FullSegment(const DictTrie* dictTrie)
: dictTrie_(dictTrie), isNeedDestroy_(false) {
assert(dictTrie_);
}
words.clear();
words.reserve(wrs.size());
GetWordsFromWordRanges(sentence, wrs, words);
}
void Cut(RuneStrArray::const_iterator begin,
RuneStrArray::const_iterator end,
vector<WordRange>& res) const {
// result of searching in trie tree
LocalVector<pair<size_t, const DictUnit*> > tRes;
// max index of res's words
size_t maxIdx = 0;
// always equals to (uItr - begin)
size_t uIdx = 0;
// tmp variables
size_t wordLen = 0;
assert(dictTrie_);
vector<struct Dag> dags;
dictTrie_->Find(begin, end, dags);
for (size_t i = 0; i < dags.size(); i++) {
for (size_t j = 0; j < dags[i].nexts.size(); j++) {
size_t nextoffset = dags[i].nexts[j].first;
assert(nextoffset < dags.size());
const DictUnit* du = dags[i].nexts[j].second;
if (du == NULL) {
if (dags[i].nexts.size() == 1 && maxIdx <= uIdx) {
WordRange wr(begin + i, begin + nextoffset);
res.push_back(wr);
}
} else {
wordLen = du->word.size();
if (wordLen >= 2 || (dags[i].nexts.size() == 1 && maxIdx <= uIdx)) {
WordRange wr(begin + i, begin + nextoffset);
res.push_back(wr);
}
~FullSegment() {
if(isNeedDestroy_) {
delete dictTrie_;
}
maxIdx = uIdx + wordLen > maxIdx ? uIdx + wordLen : maxIdx;
}
uIdx++;
}
}
private:
const DictTrie* dictTrie_;
bool isNeedDestroy_;
void Cut(const string& sentence,
vector<string>& words) const {
vector<Word> tmp;
Cut(sentence, tmp);
GetStringsFromWords(tmp, words);
}
void Cut(const string& sentence,
vector<Word>& words) const {
PreFilter pre_filter(symbols_, sentence);
PreFilter::Range range;
vector<WordRange> wrs;
wrs.reserve(sentence.size() / 2);
while(pre_filter.HasNext()) {
range = pre_filter.Next();
Cut(range.begin, range.end, wrs);
}
words.clear();
words.reserve(wrs.size());
GetWordsFromWordRanges(sentence, wrs, words);
}
void Cut(RuneStrArray::const_iterator begin,
RuneStrArray::const_iterator end,
vector<WordRange>& res) const {
// result of searching in trie tree
LocalVector<pair<size_t, const DictUnit*> > tRes;
// max index of res's words
size_t maxIdx = 0;
// always equals to (uItr - begin)
size_t uIdx = 0;
// tmp variables
size_t wordLen = 0;
assert(dictTrie_);
vector<struct Dag> dags;
dictTrie_->Find(begin, end, dags);
for(size_t i = 0; i < dags.size(); i++) {
for(size_t j = 0; j < dags[i].nexts.size(); j++) {
size_t nextoffset = dags[i].nexts[j].first;
assert(nextoffset < dags.size());
const DictUnit* du = dags[i].nexts[j].second;
if(du == NULL) {
if(dags[i].nexts.size() == 1 && maxIdx <= uIdx) {
WordRange wr(begin + i, begin + nextoffset);
res.push_back(wr);
}
} else {
wordLen = du->word.size();
if(wordLen >= 2 || (dags[i].nexts.size() == 1 && maxIdx <= uIdx)) {
WordRange wr(begin + i, begin + nextoffset);
res.push_back(wr);
}
}
maxIdx = uIdx + wordLen > maxIdx ? uIdx + wordLen : maxIdx;
}
uIdx++;
}
}
private:
const DictTrie* dictTrie_;
bool isNeedDestroy_;
};
}

View File

@ -28,118 +28,118 @@ using namespace limonp;
typedef unordered_map<Rune, double> EmitProbMap;
struct HMMModel {
/*
* STATUS:
* 0: HMMModel::B, 1: HMMModel::E, 2: HMMModel::M, 3:HMMModel::S
* */
enum {B = 0, E = 1, M = 2, S = 3, STATUS_SUM = 4};
/*
* STATUS:
* 0: HMMModel::B, 1: HMMModel::E, 2: HMMModel::M, 3:HMMModel::S
* */
enum {B = 0, E = 1, M = 2, S = 3, STATUS_SUM = 4};
HMMModel(const string& modelPath) {
memset(startProb, 0, sizeof(startProb));
memset(transProb, 0, sizeof(transProb));
statMap[0] = 'B';
statMap[1] = 'E';
statMap[2] = 'M';
statMap[3] = 'S';
emitProbVec.push_back(&emitProbB);
emitProbVec.push_back(&emitProbE);
emitProbVec.push_back(&emitProbM);
emitProbVec.push_back(&emitProbS);
LoadModel(modelPath);
}
~HMMModel() {
}
void LoadModel(const string& filePath) {
ifstream ifile(filePath.c_str());
XCHECK(ifile.is_open()) << "open " << filePath << " failed";
string line;
vector<string> tmp;
vector<string> tmp2;
//Load startProb
XCHECK(GetLine(ifile, line));
Split(line, tmp, " ");
XCHECK(tmp.size() == STATUS_SUM);
for (size_t j = 0; j< tmp.size(); j++) {
startProb[j] = atof(tmp[j].c_str());
HMMModel(const string& modelPath) {
memset(startProb, 0, sizeof(startProb));
memset(transProb, 0, sizeof(transProb));
statMap[0] = 'B';
statMap[1] = 'E';
statMap[2] = 'M';
statMap[3] = 'S';
emitProbVec.push_back(&emitProbB);
emitProbVec.push_back(&emitProbE);
emitProbVec.push_back(&emitProbM);
emitProbVec.push_back(&emitProbS);
LoadModel(modelPath);
}
//Load transProb
for (size_t i = 0; i < STATUS_SUM; i++) {
XCHECK(GetLine(ifile, line));
Split(line, tmp, " ");
XCHECK(tmp.size() == STATUS_SUM);
for (size_t j =0; j < STATUS_SUM; j++) {
transProb[i][j] = atof(tmp[j].c_str());
}
~HMMModel() {
}
void LoadModel(const string& filePath) {
ifstream ifile(filePath.c_str());
XCHECK(ifile.is_open()) << "open " << filePath << " failed";
string line;
vector<string> tmp;
vector<string> tmp2;
//Load startProb
XCHECK(GetLine(ifile, line));
Split(line, tmp, " ");
XCHECK(tmp.size() == STATUS_SUM);
for(size_t j = 0; j < tmp.size(); j++) {
startProb[j] = atof(tmp[j].c_str());
}
//Load emitProbB
XCHECK(GetLine(ifile, line));
XCHECK(LoadEmitProb(line, emitProbB));
//Load transProb
for(size_t i = 0; i < STATUS_SUM; i++) {
XCHECK(GetLine(ifile, line));
Split(line, tmp, " ");
XCHECK(tmp.size() == STATUS_SUM);
for(size_t j = 0; j < STATUS_SUM; j++) {
transProb[i][j] = atof(tmp[j].c_str());
}
}
//Load emitProbE
XCHECK(GetLine(ifile, line));
XCHECK(LoadEmitProb(line, emitProbE));
//Load emitProbB
XCHECK(GetLine(ifile, line));
XCHECK(LoadEmitProb(line, emitProbB));
//Load emitProbM
XCHECK(GetLine(ifile, line));
XCHECK(LoadEmitProb(line, emitProbM));
//Load emitProbE
XCHECK(GetLine(ifile, line));
XCHECK(LoadEmitProb(line, emitProbE));
//Load emitProbS
XCHECK(GetLine(ifile, line));
XCHECK(LoadEmitProb(line, emitProbS));
}
double GetEmitProb(const EmitProbMap* ptMp, Rune key,
double defVal)const {
EmitProbMap::const_iterator cit = ptMp->find(key);
if (cit == ptMp->end()) {
return defVal;
//Load emitProbM
XCHECK(GetLine(ifile, line));
XCHECK(LoadEmitProb(line, emitProbM));
//Load emitProbS
XCHECK(GetLine(ifile, line));
XCHECK(LoadEmitProb(line, emitProbS));
}
return cit->second;
}
bool GetLine(ifstream& ifile, string& line) {
while (getline(ifile, line)) {
Trim(line);
if (line.empty()) {
continue;
}
if (StartsWith(line, "#")) {
continue;
}
return true;
double GetEmitProb(const EmitProbMap* ptMp, Rune key,
double defVal)const {
EmitProbMap::const_iterator cit = ptMp->find(key);
if(cit == ptMp->end()) {
return defVal;
}
return cit->second;
}
return false;
}
bool LoadEmitProb(const string& line, EmitProbMap& mp) {
if (line.empty()) {
return false;
}
vector<string> tmp, tmp2;
Unicode unicode;
Split(line, tmp, ",");
for (size_t i = 0; i < tmp.size(); i++) {
Split(tmp[i], tmp2, ":");
if (2 != tmp2.size()) {
XLOG(ERROR) << "emitProb illegal.";
bool GetLine(ifstream& ifile, string& line) {
while(getline(ifile, line)) {
Trim(line);
if(line.empty()) {
continue;
}
if(StartsWith(line, "#")) {
continue;
}
return true;
}
return false;
}
if (!DecodeRunesInString(tmp2[0], unicode) || unicode.size() != 1) {
XLOG(ERROR) << "TransCode failed.";
return false;
}
mp[unicode[0]] = atof(tmp2[1].c_str());
}
return true;
}
bool LoadEmitProb(const string& line, EmitProbMap& mp) {
if(line.empty()) {
return false;
}
vector<string> tmp, tmp2;
Unicode unicode;
Split(line, tmp, ",");
for(size_t i = 0; i < tmp.size(); i++) {
Split(tmp[i], tmp2, ":");
if(2 != tmp2.size()) {
XLOG(ERROR) << "emitProb illegal.";
return false;
}
if(!DecodeRunesInString(tmp2[0], unicode) || unicode.size() != 1) {
XLOG(ERROR) << "TransCode failed.";
return false;
}
mp[unicode[0]] = atof(tmp2[1].c_str());
}
return true;
}
char statMap[STATUS_SUM];
double startProb[STATUS_SUM];
double transProb[STATUS_SUM][STATUS_SUM];
EmitProbMap emitProbB;
EmitProbMap emitProbE;
EmitProbMap emitProbM;
EmitProbMap emitProbS;
vector<EmitProbMap* > emitProbVec;
char statMap[STATUS_SUM];
double startProb[STATUS_SUM];
double transProb[STATUS_SUM][STATUS_SUM];
EmitProbMap emitProbB;
EmitProbMap emitProbE;
EmitProbMap emitProbM;
EmitProbMap emitProbS;
vector<EmitProbMap* > emitProbVec;
}; // struct HMMModel
} // namespace cppjieba

View File

@ -28,179 +28,179 @@
namespace cppjieba {
class HMMSegment: public SegmentBase {
public:
HMMSegment(const string& filePath)
: model_(new HMMModel(filePath)), isNeedDestroy_(true) {
}
HMMSegment(const HMMModel* model)
: model_(model), isNeedDestroy_(false) {
}
~HMMSegment() {
if (isNeedDestroy_) {
delete model_;
public:
HMMSegment(const string& filePath)
: model_(new HMMModel(filePath)), isNeedDestroy_(true) {
}
}
void Cut(const string& sentence,
vector<string>& words) const {
vector<Word> tmp;
Cut(sentence, tmp);
GetStringsFromWords(tmp, words);
}
void Cut(const string& sentence,
vector<Word>& words) const {
PreFilter pre_filter(symbols_, sentence);
PreFilter::Range range;
vector<WordRange> wrs;
wrs.reserve(sentence.size()/2);
while (pre_filter.HasNext()) {
range = pre_filter.Next();
Cut(range.begin, range.end, wrs);
HMMSegment(const HMMModel* model)
: model_(model), isNeedDestroy_(false) {
}
words.clear();
words.reserve(wrs.size());
GetWordsFromWordRanges(sentence, wrs, words);
}
void Cut(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end, vector<WordRange>& res) const {
RuneStrArray::const_iterator left = begin;
RuneStrArray::const_iterator right = begin;
while (right != end) {
if (right->rune < 0x80) {
if (left != right) {
InternalCut(left, right, res);
~HMMSegment() {
if(isNeedDestroy_) {
delete model_;
}
left = right;
do {
right = SequentialLetterRule(left, end);
if (right != left) {
break;
}
right = NumbersRule(left, end);
if (right != left) {
break;
}
right ++;
} while (false);
WordRange wr(left, right - 1);
res.push_back(wr);
left = right;
} else {
right++;
}
}
if (left != right) {
InternalCut(left, right, res);
}
}
private:
// sequential letters rule
RuneStrArray::const_iterator SequentialLetterRule(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end) const {
Rune x = begin->rune;
if (('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z')) {
begin ++;
} else {
return begin;
}
while (begin != end) {
x = begin->rune;
if (('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z') || ('0' <= x && x <= '9')) {
begin ++;
} else {
break;
}
}
return begin;
}
//
RuneStrArray::const_iterator NumbersRule(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end) const {
Rune x = begin->rune;
if ('0' <= x && x <= '9') {
begin ++;
} else {
return begin;
}
while (begin != end) {
x = begin->rune;
if ( ('0' <= x && x <= '9') || x == '.') {
begin++;
} else {
break;
}
}
return begin;
}
void InternalCut(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end, vector<WordRange>& res) const {
vector<size_t> status;
Viterbi(begin, end, status);
RuneStrArray::const_iterator left = begin;
RuneStrArray::const_iterator right;
for (size_t i = 0; i < status.size(); i++) {
if (status[i] % 2) { //if (HMMModel::E == status[i] || HMMModel::S == status[i])
right = begin + i + 1;
WordRange wr(left, right - 1);
res.push_back(wr);
left = right;
}
}
}
void Viterbi(RuneStrArray::const_iterator begin,
RuneStrArray::const_iterator end,
vector<size_t>& status) const {
size_t Y = HMMModel::STATUS_SUM;
size_t X = end - begin;
size_t XYSize = X * Y;
size_t now, old, stat;
double tmp, endE, endS;
vector<int> path(XYSize);
vector<double> weight(XYSize);
//start
for (size_t y = 0; y < Y; y++) {
weight[0 + y * X] = model_->startProb[y] + model_->GetEmitProb(model_->emitProbVec[y], begin->rune, MIN_DOUBLE);
path[0 + y * X] = -1;
}
double emitProb;
for (size_t x = 1; x < X; x++) {
for (size_t y = 0; y < Y; y++) {
now = x + y*X;
weight[now] = MIN_DOUBLE;
path[now] = HMMModel::E; // warning
emitProb = model_->GetEmitProb(model_->emitProbVec[y], (begin+x)->rune, MIN_DOUBLE);
for (size_t preY = 0; preY < Y; preY++) {
old = x - 1 + preY * X;
tmp = weight[old] + model_->transProb[preY][y] + emitProb;
if (tmp > weight[now]) {
weight[now] = tmp;
path[now] = preY;
}
void Cut(const string& sentence,
vector<string>& words) const {
vector<Word> tmp;
Cut(sentence, tmp);
GetStringsFromWords(tmp, words);
}
void Cut(const string& sentence,
vector<Word>& words) const {
PreFilter pre_filter(symbols_, sentence);
PreFilter::Range range;
vector<WordRange> wrs;
wrs.reserve(sentence.size() / 2);
while(pre_filter.HasNext()) {
range = pre_filter.Next();
Cut(range.begin, range.end, wrs);
}
words.clear();
words.reserve(wrs.size());
GetWordsFromWordRanges(sentence, wrs, words);
}
void Cut(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end, vector<WordRange>& res) const {
RuneStrArray::const_iterator left = begin;
RuneStrArray::const_iterator right = begin;
while(right != end) {
if(right->rune < 0x80) {
if(left != right) {
InternalCut(left, right, res);
}
left = right;
do {
right = SequentialLetterRule(left, end);
if(right != left) {
break;
}
right = NumbersRule(left, end);
if(right != left) {
break;
}
right ++;
} while(false);
WordRange wr(left, right - 1);
res.push_back(wr);
left = right;
} else {
right++;
}
}
if(left != right) {
InternalCut(left, right, res);
}
}
private:
// sequential letters rule
RuneStrArray::const_iterator SequentialLetterRule(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end) const {
Rune x = begin->rune;
if(('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z')) {
begin ++;
} else {
return begin;
}
while(begin != end) {
x = begin->rune;
if(('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z') || ('0' <= x && x <= '9')) {
begin ++;
} else {
break;
}
}
return begin;
}
//
RuneStrArray::const_iterator NumbersRule(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end) const {
Rune x = begin->rune;
if('0' <= x && x <= '9') {
begin ++;
} else {
return begin;
}
while(begin != end) {
x = begin->rune;
if(('0' <= x && x <= '9') || x == '.') {
begin++;
} else {
break;
}
}
return begin;
}
void InternalCut(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end, vector<WordRange>& res) const {
vector<size_t> status;
Viterbi(begin, end, status);
RuneStrArray::const_iterator left = begin;
RuneStrArray::const_iterator right;
for(size_t i = 0; i < status.size(); i++) {
if(status[i] % 2) { //if (HMMModel::E == status[i] || HMMModel::S == status[i])
right = begin + i + 1;
WordRange wr(left, right - 1);
res.push_back(wr);
left = right;
}
}
}
}
endE = weight[X-1+HMMModel::E*X];
endS = weight[X-1+HMMModel::S*X];
stat = 0;
if (endE >= endS) {
stat = HMMModel::E;
} else {
stat = HMMModel::S;
void Viterbi(RuneStrArray::const_iterator begin,
RuneStrArray::const_iterator end,
vector<size_t>& status) const {
size_t Y = HMMModel::STATUS_SUM;
size_t X = end - begin;
size_t XYSize = X * Y;
size_t now, old, stat;
double tmp, endE, endS;
vector<int> path(XYSize);
vector<double> weight(XYSize);
//start
for(size_t y = 0; y < Y; y++) {
weight[0 + y * X] = model_->startProb[y] + model_->GetEmitProb(model_->emitProbVec[y], begin->rune, MIN_DOUBLE);
path[0 + y * X] = -1;
}
double emitProb;
for(size_t x = 1; x < X; x++) {
for(size_t y = 0; y < Y; y++) {
now = x + y * X;
weight[now] = MIN_DOUBLE;
path[now] = HMMModel::E; // warning
emitProb = model_->GetEmitProb(model_->emitProbVec[y], (begin + x)->rune, MIN_DOUBLE);
for(size_t preY = 0; preY < Y; preY++) {
old = x - 1 + preY * X;
tmp = weight[old] + model_->transProb[preY][y] + emitProb;
if(tmp > weight[now]) {
weight[now] = tmp;
path[now] = preY;
}
}
}
}
endE = weight[X - 1 + HMMModel::E * X];
endS = weight[X - 1 + HMMModel::S * X];
stat = 0;
if(endE >= endS) {
stat = HMMModel::E;
} else {
stat = HMMModel::S;
}
status.resize(X);
for(int x = X - 1 ; x >= 0; x--) {
status[x] = stat;
stat = path[x + stat * X];
}
}
status.resize(X);
for (int x = X -1 ; x >= 0; x--) {
status[x] = stat;
stat = path[x + stat*X];
}
}
const HMMModel* model_;
bool isNeedDestroy_;
const HMMModel* model_;
bool isNeedDestroy_;
}; // class HMMSegment
} // namespace cppjieba

View File

@ -25,123 +25,122 @@
namespace cppjieba {
class Jieba {
public:
Jieba(const string& dict_path,
const string& model_path,
const string& user_dict_path,
const string& idfPath,
const string& stopWordPath)
: dict_trie_(dict_path, user_dict_path),
model_(model_path),
mp_seg_(&dict_trie_),
hmm_seg_(&model_),
mix_seg_(&dict_trie_, &model_),
full_seg_(&dict_trie_),
query_seg_(&dict_trie_, &model_),
extractor(&dict_trie_, &model_, idfPath, stopWordPath) {
public:
Jieba(const string& dict_path,
const string& model_path,
const string& user_dict_path,
const string& idfPath,
const string& stopWordPath)
: dict_trie_(dict_path, user_dict_path),
model_(model_path),
mp_seg_(&dict_trie_),
hmm_seg_(&model_),
mix_seg_(&dict_trie_, &model_),
full_seg_(&dict_trie_),
query_seg_(&dict_trie_, &model_),
extractor(&dict_trie_, &model_, idfPath, stopWordPath) {
}
~Jieba() {
}
}
~Jieba() {
}
struct LocWord {
string word;
size_t begin;
size_t end;
}; // struct LocWord
struct LocWord {
string word;
size_t begin;
size_t end;
}; // struct LocWord
void Cut(const string& sentence, vector<string>& words, bool hmm = true) const {
mix_seg_.Cut(sentence, words, hmm);
}
void Cut(const string& sentence, vector<Word>& words, bool hmm = true) const {
mix_seg_.Cut(sentence, words, hmm);
}
void CutAll(const string& sentence, vector<string>& words) const {
full_seg_.Cut(sentence, words);
}
void CutAll(const string& sentence, vector<Word>& words) const {
full_seg_.Cut(sentence, words);
}
void CutForSearch(const string& sentence, vector<string>& words, bool hmm = true) const {
query_seg_.Cut(sentence, words, hmm);
}
void CutForSearch(const string& sentence, vector<Word>& words, bool hmm = true) const {
query_seg_.Cut(sentence, words, hmm);
}
void CutHMM(const string& sentence, vector<string>& words) const {
hmm_seg_.Cut(sentence, words);
}
void CutHMM(const string& sentence, vector<Word>& words) const {
hmm_seg_.Cut(sentence, words);
}
void CutSmall(const string& sentence, vector<string>& words, size_t max_word_len) const {
mp_seg_.Cut(sentence, words, max_word_len);
}
void CutSmall(const string& sentence, vector<Word>& words, size_t max_word_len) const {
mp_seg_.Cut(sentence, words, max_word_len);
}
void Tag(const string& sentence, vector<pair<string, string> >& words) const {
mix_seg_.Tag(sentence, words);
}
string LookupTag(const string &str) const {
return mix_seg_.LookupTag(str);
}
bool InsertUserWord(const string& word, const string& tag = UNKNOWN_TAG) {
return dict_trie_.InsertUserWord(word, tag);
}
void Cut(const string& sentence, vector<string>& words, bool hmm = true) const {
mix_seg_.Cut(sentence, words, hmm);
}
void Cut(const string& sentence, vector<Word>& words, bool hmm = true) const {
mix_seg_.Cut(sentence, words, hmm);
}
void CutAll(const string& sentence, vector<string>& words) const {
full_seg_.Cut(sentence, words);
}
void CutAll(const string& sentence, vector<Word>& words) const {
full_seg_.Cut(sentence, words);
}
void CutForSearch(const string& sentence, vector<string>& words, bool hmm = true) const {
query_seg_.Cut(sentence, words, hmm);
}
void CutForSearch(const string& sentence, vector<Word>& words, bool hmm = true) const {
query_seg_.Cut(sentence, words, hmm);
}
void CutHMM(const string& sentence, vector<string>& words) const {
hmm_seg_.Cut(sentence, words);
}
void CutHMM(const string& sentence, vector<Word>& words) const {
hmm_seg_.Cut(sentence, words);
}
void CutSmall(const string& sentence, vector<string>& words, size_t max_word_len) const {
mp_seg_.Cut(sentence, words, max_word_len);
}
void CutSmall(const string& sentence, vector<Word>& words, size_t max_word_len) const {
mp_seg_.Cut(sentence, words, max_word_len);
}
bool InsertUserWord(const string& word,int freq, const string& tag = UNKNOWN_TAG) {
return dict_trie_.InsertUserWord(word,freq, tag);
}
void Tag(const string& sentence, vector<pair<string, string> >& words) const {
mix_seg_.Tag(sentence, words);
}
string LookupTag(const string &str) const {
return mix_seg_.LookupTag(str);
}
bool InsertUserWord(const string& word, const string& tag = UNKNOWN_TAG) {
return dict_trie_.InsertUserWord(word, tag);
}
bool Find(const string& word)
{
return dict_trie_.Find(word);
}
bool InsertUserWord(const string& word, int freq, const string& tag = UNKNOWN_TAG) {
return dict_trie_.InsertUserWord(word, freq, tag);
}
void ResetSeparators(const string& s) {
//TODO
mp_seg_.ResetSeparators(s);
hmm_seg_.ResetSeparators(s);
mix_seg_.ResetSeparators(s);
full_seg_.ResetSeparators(s);
query_seg_.ResetSeparators(s);
}
bool Find(const string& word) {
return dict_trie_.Find(word);
}
const DictTrie* GetDictTrie() const {
return &dict_trie_;
}
const HMMModel* GetHMMModel() const {
return &model_;
}
void ResetSeparators(const string& s) {
//TODO
mp_seg_.ResetSeparators(s);
hmm_seg_.ResetSeparators(s);
mix_seg_.ResetSeparators(s);
full_seg_.ResetSeparators(s);
query_seg_.ResetSeparators(s);
}
void LoadUserDict(const vector<string>& buf) {
dict_trie_.LoadUserDict(buf);
}
const DictTrie* GetDictTrie() const {
return &dict_trie_;
}
void LoadUserDict(const set<string>& buf) {
dict_trie_.LoadUserDict(buf);
}
const HMMModel* GetHMMModel() const {
return &model_;
}
void LoadUserDict(const string& path) {
dict_trie_.LoadUserDict(path);
}
void LoadUserDict(const vector<string>& buf) {
dict_trie_.LoadUserDict(buf);
}
private:
DictTrie dict_trie_;
HMMModel model_;
// They share the same dict trie and model
MPSegment mp_seg_;
HMMSegment hmm_seg_;
MixSegment mix_seg_;
FullSegment full_seg_;
QuerySegment query_seg_;
void LoadUserDict(const set<string>& buf) {
dict_trie_.LoadUserDict(buf);
}
public:
KeywordExtractor extractor;
void LoadUserDict(const string& path) {
dict_trie_.LoadUserDict(path);
}
private:
DictTrie dict_trie_;
HMMModel model_;
// They share the same dict trie and model
MPSegment mp_seg_;
HMMSegment hmm_seg_;
MixSegment mix_seg_;
FullSegment full_seg_;
QuerySegment query_seg_;
public:
KeywordExtractor extractor;
}; // class Jieba
} // namespace cppjieba

View File

@ -30,138 +30,138 @@ using namespace std;
/*utf8*/
class KeywordExtractor {
public:
struct Word {
string word;
vector<size_t> offsets;
double weight;
}; // struct Word
public:
struct Word {
string word;
vector<size_t> offsets;
double weight;
}; // struct Word
KeywordExtractor(const string& dictPath,
const string& hmmFilePath,
const string& idfPath,
const string& stopWordPath,
const string& userDict = "")
: segment_(dictPath, hmmFilePath, userDict) {
LoadIdfDict(idfPath);
LoadStopWordDict(stopWordPath);
}
KeywordExtractor(const DictTrie* dictTrie,
const HMMModel* model,
const string& idfPath,
const string& stopWordPath)
: segment_(dictTrie, model) {
LoadIdfDict(idfPath);
LoadStopWordDict(stopWordPath);
}
~KeywordExtractor() {
}
void Extract(const string& sentence, vector<string>& keywords, size_t topN) const {
vector<Word> topWords;
Extract(sentence, topWords, topN);
for (size_t i = 0; i < topWords.size(); i++) {
keywords.push_back(topWords[i].word);
KeywordExtractor(const string& dictPath,
const string& hmmFilePath,
const string& idfPath,
const string& stopWordPath,
const string& userDict = "")
: segment_(dictPath, hmmFilePath, userDict) {
LoadIdfDict(idfPath);
LoadStopWordDict(stopWordPath);
}
}
void Extract(const string& sentence, vector<pair<string, double> >& keywords, size_t topN) const {
vector<Word> topWords;
Extract(sentence, topWords, topN);
for (size_t i = 0; i < topWords.size(); i++) {
keywords.push_back(pair<string, double>(topWords[i].word, topWords[i].weight));
KeywordExtractor(const DictTrie* dictTrie,
const HMMModel* model,
const string& idfPath,
const string& stopWordPath)
: segment_(dictTrie, model) {
LoadIdfDict(idfPath);
LoadStopWordDict(stopWordPath);
}
}
void Extract(const string& sentence, vector<Word>& keywords, size_t topN) const {
vector<string> words;
segment_.Cut(sentence, words);
map<string, Word> wordmap;
size_t offset = 0;
for (size_t i = 0; i < words.size(); ++i) {
size_t t = offset;
offset += words[i].size();
if (IsSingleWord(words[i]) || stopWords_.find(words[i]) != stopWords_.end()) {
continue;
}
wordmap[words[i]].offsets.push_back(t);
wordmap[words[i]].weight += 1.0;
}
if (offset != sentence.size()) {
XLOG(ERROR) << "words illegal";
return;
~KeywordExtractor() {
}
keywords.clear();
keywords.reserve(wordmap.size());
for (map<string, Word>::iterator itr = wordmap.begin(); itr != wordmap.end(); ++itr) {
unordered_map<string, double>::const_iterator cit = idfMap_.find(itr->first);
if (cit != idfMap_.end()) {
itr->second.weight *= cit->second;
} else {
itr->second.weight *= idfAverage_;
}
itr->second.word = itr->first;
keywords.push_back(itr->second);
}
topN = min(topN, keywords.size());
partial_sort(keywords.begin(), keywords.begin() + topN, keywords.end(), Compare);
keywords.resize(topN);
}
private:
void LoadIdfDict(const string& idfPath) {
ifstream ifs(idfPath.c_str());
XCHECK(ifs.is_open()) << "open " << idfPath << " failed";
string line ;
vector<string> buf;
double idf = 0.0;
double idfSum = 0.0;
size_t lineno = 0;
for (; getline(ifs, line); lineno++) {
buf.clear();
if (line.empty()) {
XLOG(ERROR) << "lineno: " << lineno << " empty. skipped.";
continue;
}
Split(line, buf, " ");
if (buf.size() != 2) {
XLOG(ERROR) << "line: " << line << ", lineno: " << lineno << " empty. skipped.";
continue;
}
idf = atof(buf[1].c_str());
idfMap_[buf[0]] = idf;
idfSum += idf;
void Extract(const string& sentence, vector<string>& keywords, size_t topN) const {
vector<Word> topWords;
Extract(sentence, topWords, topN);
for(size_t i = 0; i < topWords.size(); i++) {
keywords.push_back(topWords[i].word);
}
}
assert(lineno);
idfAverage_ = idfSum / lineno;
assert(idfAverage_ > 0.0);
}
void LoadStopWordDict(const string& filePath) {
ifstream ifs(filePath.c_str());
XCHECK(ifs.is_open()) << "open " << filePath << " failed";
string line ;
while (getline(ifs, line)) {
stopWords_.insert(line);
void Extract(const string& sentence, vector<pair<string, double> >& keywords, size_t topN) const {
vector<Word> topWords;
Extract(sentence, topWords, topN);
for(size_t i = 0; i < topWords.size(); i++) {
keywords.push_back(pair<string, double>(topWords[i].word, topWords[i].weight));
}
}
assert(stopWords_.size());
}
static bool Compare(const Word& lhs, const Word& rhs) {
return lhs.weight > rhs.weight;
}
void Extract(const string& sentence, vector<Word>& keywords, size_t topN) const {
vector<string> words;
segment_.Cut(sentence, words);
MixSegment segment_;
unordered_map<string, double> idfMap_;
double idfAverage_;
map<string, Word> wordmap;
size_t offset = 0;
for(size_t i = 0; i < words.size(); ++i) {
size_t t = offset;
offset += words[i].size();
if(IsSingleWord(words[i]) || stopWords_.find(words[i]) != stopWords_.end()) {
continue;
}
wordmap[words[i]].offsets.push_back(t);
wordmap[words[i]].weight += 1.0;
}
if(offset != sentence.size()) {
XLOG(ERROR) << "words illegal";
return;
}
unordered_set<string> stopWords_;
keywords.clear();
keywords.reserve(wordmap.size());
for(map<string, Word>::iterator itr = wordmap.begin(); itr != wordmap.end(); ++itr) {
unordered_map<string, double>::const_iterator cit = idfMap_.find(itr->first);
if(cit != idfMap_.end()) {
itr->second.weight *= cit->second;
} else {
itr->second.weight *= idfAverage_;
}
itr->second.word = itr->first;
keywords.push_back(itr->second);
}
topN = min(topN, keywords.size());
partial_sort(keywords.begin(), keywords.begin() + topN, keywords.end(), Compare);
keywords.resize(topN);
}
private:
void LoadIdfDict(const string& idfPath) {
ifstream ifs(idfPath.c_str());
XCHECK(ifs.is_open()) << "open " << idfPath << " failed";
string line ;
vector<string> buf;
double idf = 0.0;
double idfSum = 0.0;
size_t lineno = 0;
for(; getline(ifs, line); lineno++) {
buf.clear();
if(line.empty()) {
XLOG(ERROR) << "lineno: " << lineno << " empty. skipped.";
continue;
}
Split(line, buf, " ");
if(buf.size() != 2) {
XLOG(ERROR) << "line: " << line << ", lineno: " << lineno << " empty. skipped.";
continue;
}
idf = atof(buf[1].c_str());
idfMap_[buf[0]] = idf;
idfSum += idf;
}
assert(lineno);
idfAverage_ = idfSum / lineno;
assert(idfAverage_ > 0.0);
}
void LoadStopWordDict(const string& filePath) {
ifstream ifs(filePath.c_str());
XCHECK(ifs.is_open()) << "open " << filePath << " failed";
string line ;
while(getline(ifs, line)) {
stopWords_.insert(line);
}
assert(stopWords_.size());
}
static bool Compare(const Word& lhs, const Word& rhs) {
return lhs.weight > rhs.weight;
}
MixSegment segment_;
unordered_map<string, double> idfMap_;
double idfAverage_;
unordered_set<string> stopWords_;
}; // class KeywordExtractor
inline ostream& operator << (ostream& os, const KeywordExtractor::Word& word) {
return os << "{\"word\": \"" << word.word << "\", \"offset\": " << word.offsets << ", \"weight\": " << word.weight << "}";
return os << "{\"word\": \"" << word.word << "\", \"offset\": " << word.offsets << ", \"weight\": " << word.weight << "}";
}
} // namespace cppjieba

View File

@ -30,123 +30,123 @@
namespace cppjieba {
class MPSegment: public SegmentTagged {
public:
MPSegment(const string& dictPath, const string& userDictPath = "")
: dictTrie_(new DictTrie(dictPath, userDictPath)), isNeedDestroy_(true) {
}
MPSegment(const DictTrie* dictTrie)
: dictTrie_(dictTrie), isNeedDestroy_(false) {
assert(dictTrie_);
}
~MPSegment() {
if (isNeedDestroy_) {
delete dictTrie_;
public:
MPSegment(const string& dictPath, const string& userDictPath = "")
: dictTrie_(new DictTrie(dictPath, userDictPath)), isNeedDestroy_(true) {
}
}
void Cut(const string& sentence, vector<string>& words) const {
Cut(sentence, words, MAX_WORD_LENGTH);
}
void Cut(const string& sentence,
vector<string>& words,
size_t max_word_len) const {
vector<Word> tmp;
Cut(sentence, tmp, max_word_len);
GetStringsFromWords(tmp, words);
}
void Cut(const string& sentence,
vector<Word>& words,
size_t max_word_len = MAX_WORD_LENGTH) const {
PreFilter pre_filter(symbols_, sentence);
PreFilter::Range range;
vector<WordRange> wrs;
wrs.reserve(sentence.size()/2);
while (pre_filter.HasNext()) {
range = pre_filter.Next();
Cut(range.begin, range.end, wrs, max_word_len);
MPSegment(const DictTrie* dictTrie)
: dictTrie_(dictTrie), isNeedDestroy_(false) {
assert(dictTrie_);
}
words.clear();
words.reserve(wrs.size());
GetWordsFromWordRanges(sentence, wrs, words);
}
void Cut(RuneStrArray::const_iterator begin,
RuneStrArray::const_iterator end,
vector<WordRange>& words,
size_t max_word_len = MAX_WORD_LENGTH) const {
vector<Dag> dags;
dictTrie_->Find(begin,
end,
dags,
max_word_len);
CalcDP(dags);
CutByDag(begin, end, dags, words);
}
const DictTrie* GetDictTrie() const {
return dictTrie_;
}
bool Tag(const string& src, vector<pair<string, string> >& res) const {
return tagger_.Tag(src, res, *this);
}
bool IsUserDictSingleChineseWord(const Rune& value) const {
return dictTrie_->IsUserDictSingleChineseWord(value);
}
private:
void CalcDP(vector<Dag>& dags) const {
size_t nextPos;
const DictUnit* p;
double val;
for (vector<Dag>::reverse_iterator rit = dags.rbegin(); rit != dags.rend(); rit++) {
rit->pInfo = NULL;
rit->weight = MIN_DOUBLE;
assert(!rit->nexts.empty());
for (LocalVector<pair<size_t, const DictUnit*> >::const_iterator it = rit->nexts.begin(); it != rit->nexts.end(); it++) {
nextPos = it->first;
p = it->second;
val = 0.0;
if (nextPos + 1 < dags.size()) {
val += dags[nextPos + 1].weight;
~MPSegment() {
if(isNeedDestroy_) {
delete dictTrie_;
}
if (p) {
val += p->weight;
} else {
val += dictTrie_->GetMinWeight();
}
if (val > rit->weight) {
rit->pInfo = p;
rit->weight = val;
}
}
}
}
void CutByDag(RuneStrArray::const_iterator begin,
RuneStrArray::const_iterator end,
const vector<Dag>& dags,
vector<WordRange>& words) const {
size_t i = 0;
while (i < dags.size()) {
const DictUnit* p = dags[i].pInfo;
if (p) {
assert(p->word.size() >= 1);
WordRange wr(begin + i, begin + i + p->word.size() - 1);
words.push_back(wr);
i += p->word.size();
} else { //single chinese word
WordRange wr(begin + i, begin + i);
words.push_back(wr);
i++;
}
}
}
const DictTrie* dictTrie_;
bool isNeedDestroy_;
PosTagger tagger_;
void Cut(const string& sentence, vector<string>& words) const {
Cut(sentence, words, MAX_WORD_LENGTH);
}
void Cut(const string& sentence,
vector<string>& words,
size_t max_word_len) const {
vector<Word> tmp;
Cut(sentence, tmp, max_word_len);
GetStringsFromWords(tmp, words);
}
void Cut(const string& sentence,
vector<Word>& words,
size_t max_word_len = MAX_WORD_LENGTH) const {
PreFilter pre_filter(symbols_, sentence);
PreFilter::Range range;
vector<WordRange> wrs;
wrs.reserve(sentence.size() / 2);
while(pre_filter.HasNext()) {
range = pre_filter.Next();
Cut(range.begin, range.end, wrs, max_word_len);
}
words.clear();
words.reserve(wrs.size());
GetWordsFromWordRanges(sentence, wrs, words);
}
void Cut(RuneStrArray::const_iterator begin,
RuneStrArray::const_iterator end,
vector<WordRange>& words,
size_t max_word_len = MAX_WORD_LENGTH) const {
vector<Dag> dags;
dictTrie_->Find(begin,
end,
dags,
max_word_len);
CalcDP(dags);
CutByDag(begin, end, dags, words);
}
const DictTrie* GetDictTrie() const {
return dictTrie_;
}
bool Tag(const string& src, vector<pair<string, string> >& res) const {
return tagger_.Tag(src, res, *this);
}
bool IsUserDictSingleChineseWord(const Rune& value) const {
return dictTrie_->IsUserDictSingleChineseWord(value);
}
private:
void CalcDP(vector<Dag>& dags) const {
size_t nextPos;
const DictUnit* p;
double val;
for(vector<Dag>::reverse_iterator rit = dags.rbegin(); rit != dags.rend(); rit++) {
rit->pInfo = NULL;
rit->weight = MIN_DOUBLE;
assert(!rit->nexts.empty());
for(LocalVector<pair<size_t, const DictUnit*> >::const_iterator it = rit->nexts.begin(); it != rit->nexts.end(); it++) {
nextPos = it->first;
p = it->second;
val = 0.0;
if(nextPos + 1 < dags.size()) {
val += dags[nextPos + 1].weight;
}
if(p) {
val += p->weight;
} else {
val += dictTrie_->GetMinWeight();
}
if(val > rit->weight) {
rit->pInfo = p;
rit->weight = val;
}
}
}
}
void CutByDag(RuneStrArray::const_iterator begin,
RuneStrArray::const_iterator end,
const vector<Dag>& dags,
vector<WordRange>& words) const {
size_t i = 0;
while(i < dags.size()) {
const DictUnit* p = dags[i].pInfo;
if(p) {
assert(p->word.size() >= 1);
WordRange wr(begin + i, begin + i + p->word.size() - 1);
words.push_back(wr);
i += p->word.size();
} else { //single chinese word
WordRange wr(begin + i, begin + i);
words.push_back(wr);
i++;
}
}
}
const DictTrie* dictTrie_;
bool isNeedDestroy_;
PosTagger tagger_;
}; // class MPSegment

View File

@ -27,98 +27,98 @@
namespace cppjieba {
class MixSegment: public SegmentTagged {
public:
MixSegment(const string& mpSegDict, const string& hmmSegDict,
const string& userDict = "")
: mpSeg_(mpSegDict, userDict),
hmmSeg_(hmmSegDict) {
}
MixSegment(const DictTrie* dictTrie, const HMMModel* model)
: mpSeg_(dictTrie), hmmSeg_(model) {
}
~MixSegment() {
}
void Cut(const string& sentence, vector<string>& words) const {
Cut(sentence, words, true);
}
void Cut(const string& sentence, vector<string>& words, bool hmm) const {
vector<Word> tmp;
Cut(sentence, tmp, hmm);
GetStringsFromWords(tmp, words);
}
void Cut(const string& sentence, vector<Word>& words, bool hmm = true) const {
PreFilter pre_filter(symbols_, sentence);
PreFilter::Range range;
vector<WordRange> wrs;
wrs.reserve(sentence.size() / 2);
while (pre_filter.HasNext()) {
range = pre_filter.Next();
Cut(range.begin, range.end, wrs, hmm);
public:
MixSegment(const string& mpSegDict, const string& hmmSegDict,
const string& userDict = "")
: mpSeg_(mpSegDict, userDict),
hmmSeg_(hmmSegDict) {
}
words.clear();
words.reserve(wrs.size());
GetWordsFromWordRanges(sentence, wrs, words);
}
void Cut(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end, vector<WordRange>& res, bool hmm) const {
if (!hmm) {
mpSeg_.Cut(begin, end, res);
return;
MixSegment(const DictTrie* dictTrie, const HMMModel* model)
: mpSeg_(dictTrie), hmmSeg_(model) {
}
vector<WordRange> words;
assert(end >= begin);
words.reserve(end - begin);
mpSeg_.Cut(begin, end, words);
vector<WordRange> hmmRes;
hmmRes.reserve(end - begin);
for (size_t i = 0; i < words.size(); i++) {
//if mp Get a word, it's ok, put it into result
if (words[i].left != words[i].right || (words[i].left == words[i].right && mpSeg_.IsUserDictSingleChineseWord(words[i].left->rune))) {
res.push_back(words[i]);
continue;
}
// if mp Get a single one and it is not in userdict, collect it in sequence
size_t j = i;
while (j < words.size() && words[j].left == words[j].right && !mpSeg_.IsUserDictSingleChineseWord(words[j].left->rune)) {
j++;
}
// Cut the sequence with hmm
assert(j - 1 >= i);
// TODO
hmmSeg_.Cut(words[i].left, words[j - 1].left + 1, hmmRes);
//put hmm result to result
for (size_t k = 0; k < hmmRes.size(); k++) {
res.push_back(hmmRes[k]);
}
//clear tmp vars
hmmRes.clear();
//let i jump over this piece
i = j - 1;
~MixSegment() {
}
}
const DictTrie* GetDictTrie() const {
return mpSeg_.GetDictTrie();
}
void Cut(const string& sentence, vector<string>& words) const {
Cut(sentence, words, true);
}
void Cut(const string& sentence, vector<string>& words, bool hmm) const {
vector<Word> tmp;
Cut(sentence, tmp, hmm);
GetStringsFromWords(tmp, words);
}
void Cut(const string& sentence, vector<Word>& words, bool hmm = true) const {
PreFilter pre_filter(symbols_, sentence);
PreFilter::Range range;
vector<WordRange> wrs;
wrs.reserve(sentence.size() / 2);
while(pre_filter.HasNext()) {
range = pre_filter.Next();
Cut(range.begin, range.end, wrs, hmm);
}
words.clear();
words.reserve(wrs.size());
GetWordsFromWordRanges(sentence, wrs, words);
}
bool Tag(const string& src, vector<pair<string, string> >& res) const {
return tagger_.Tag(src, res, *this);
}
void Cut(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end, vector<WordRange>& res, bool hmm) const {
if(!hmm) {
mpSeg_.Cut(begin, end, res);
return;
}
vector<WordRange> words;
assert(end >= begin);
words.reserve(end - begin);
mpSeg_.Cut(begin, end, words);
string LookupTag(const string &str) const {
return tagger_.LookupTag(str, *this);
}
vector<WordRange> hmmRes;
hmmRes.reserve(end - begin);
for(size_t i = 0; i < words.size(); i++) {
//if mp Get a word, it's ok, put it into result
if(words[i].left != words[i].right || (words[i].left == words[i].right && mpSeg_.IsUserDictSingleChineseWord(words[i].left->rune))) {
res.push_back(words[i]);
continue;
}
private:
MPSegment mpSeg_;
HMMSegment hmmSeg_;
PosTagger tagger_;
// if mp Get a single one and it is not in userdict, collect it in sequence
size_t j = i;
while(j < words.size() && words[j].left == words[j].right && !mpSeg_.IsUserDictSingleChineseWord(words[j].left->rune)) {
j++;
}
// Cut the sequence with hmm
assert(j - 1 >= i);
// TODO
hmmSeg_.Cut(words[i].left, words[j - 1].left + 1, hmmRes);
//put hmm result to result
for(size_t k = 0; k < hmmRes.size(); k++) {
res.push_back(hmmRes[k]);
}
//clear tmp vars
hmmRes.clear();
//let i jump over this piece
i = j - 1;
}
}
const DictTrie* GetDictTrie() const {
return mpSeg_.GetDictTrie();
}
bool Tag(const string& src, vector<pair<string, string> >& res) const {
return tagger_.Tag(src, res, *this);
}
string LookupTag(const string &str) const {
return tagger_.LookupTag(str, *this);
}
private:
MPSegment mpSeg_;
HMMSegment hmmSeg_;
PosTagger tagger_;
}; // class MixSegment

View File

@ -31,62 +31,62 @@ static const char* const POS_ENG = "eng";
static const char* const POS_X = "x";
class PosTagger {
public:
PosTagger() {
}
~PosTagger() {
}
bool Tag(const string& src, vector<pair<string, string> >& res, const SegmentTagged& segment) const {
vector<string> CutRes;
segment.Cut(src, CutRes);
for (vector<string>::iterator itr = CutRes.begin(); itr != CutRes.end(); ++itr) {
res.push_back(make_pair(*itr, LookupTag(*itr, segment)));
public:
PosTagger() {
}
~PosTagger() {
}
return !res.empty();
}
string LookupTag(const string &str, const SegmentTagged& segment) const {
const DictUnit *tmp = NULL;
RuneStrArray runes;
const DictTrie * dict = segment.GetDictTrie();
assert(dict != NULL);
if (!DecodeRunesInString(str, runes)) {
XLOG(ERROR) << "Decode failed.";
return POS_X;
}
tmp = dict->Find(runes.begin(), runes.end());
if (tmp == NULL || tmp->tag.empty()) {
return SpecialRule(runes);
} else {
return tmp->tag;
}
}
bool Tag(const string& src, vector<pair<string, string> >& res, const SegmentTagged& segment) const {
vector<string> CutRes;
segment.Cut(src, CutRes);
private:
const char* SpecialRule(const RuneStrArray& unicode) const {
size_t m = 0;
size_t eng = 0;
for (size_t i = 0; i < unicode.size() && eng < unicode.size() / 2; i++) {
if (unicode[i].rune < 0x80) {
eng ++;
if ('0' <= unicode[i].rune && unicode[i].rune <= '9') {
m++;
for(vector<string>::iterator itr = CutRes.begin(); itr != CutRes.end(); ++itr) {
res.push_back(make_pair(*itr, LookupTag(*itr, segment)));
}
}
return !res.empty();
}
// ascii char is not found
if (eng == 0) {
return POS_X;
string LookupTag(const string &str, const SegmentTagged& segment) const {
const DictUnit *tmp = NULL;
RuneStrArray runes;
const DictTrie * dict = segment.GetDictTrie();
assert(dict != NULL);
if(!DecodeRunesInString(str, runes)) {
XLOG(ERROR) << "Decode failed.";
return POS_X;
}
tmp = dict->Find(runes.begin(), runes.end());
if(tmp == NULL || tmp->tag.empty()) {
return SpecialRule(runes);
} else {
return tmp->tag;
}
}
// all the ascii is number char
if (m == eng) {
return POS_M;
private:
const char* SpecialRule(const RuneStrArray& unicode) const {
size_t m = 0;
size_t eng = 0;
for(size_t i = 0; i < unicode.size() && eng < unicode.size() / 2; i++) {
if(unicode[i].rune < 0x80) {
eng ++;
if('0' <= unicode[i].rune && unicode[i].rune <= '9') {
m++;
}
}
}
// ascii char is not found
if(eng == 0) {
return POS_X;
}
// all the ascii is number char
if(m == eng) {
return POS_M;
}
// the ascii chars contain english letter
return POS_ENG;
}
// the ascii chars contain english letter
return POS_ENG;
}
}; // class PosTagger

View File

@ -25,46 +25,46 @@
namespace cppjieba {
class PreFilter {
public:
//TODO use WordRange instead of Range
struct Range {
RuneStrArray::const_iterator begin;
RuneStrArray::const_iterator end;
}; // struct Range
public:
//TODO use WordRange instead of Range
struct Range {
RuneStrArray::const_iterator begin;
RuneStrArray::const_iterator end;
}; // struct Range
PreFilter(const unordered_set<Rune>& symbols,
const string& sentence)
: symbols_(symbols) {
if (!DecodeRunesInString(sentence, sentence_)) {
XLOG(ERROR) << "decode failed. ";
}
cursor_ = sentence_.begin();
}
~PreFilter() {
}
bool HasNext() const {
return cursor_ != sentence_.end();
}
Range Next() {
Range range;
range.begin = cursor_;
while (cursor_ != sentence_.end()) {
if (IsIn(symbols_, cursor_->rune)) {
if (range.begin == cursor_) {
cursor_ ++;
PreFilter(const unordered_set<Rune>& symbols,
const string& sentence)
: symbols_(symbols) {
if(!DecodeRunesInString(sentence, sentence_)) {
XLOG(ERROR) << "decode failed. ";
}
range.end = cursor_;
return range;
}
cursor_ ++;
cursor_ = sentence_.begin();
}
range.end = sentence_.end();
return range;
}
private:
RuneStrArray::const_iterator cursor_;
RuneStrArray sentence_;
const unordered_set<Rune>& symbols_;
~PreFilter() {
}
bool HasNext() const {
return cursor_ != sentence_.end();
}
Range Next() {
Range range;
range.begin = cursor_;
while(cursor_ != sentence_.end()) {
if(IsIn(symbols_, cursor_->rune)) {
if(range.begin == cursor_) {
cursor_ ++;
}
range.end = cursor_;
return range;
}
cursor_ ++;
}
range.end = sentence_.end();
return range;
}
private:
RuneStrArray::const_iterator cursor_;
RuneStrArray sentence_;
const unordered_set<Rune>& symbols_;
}; // class PreFilter
} // namespace cppjieba

View File

@ -31,75 +31,75 @@
namespace cppjieba {
class QuerySegment: public SegmentBase {
public:
QuerySegment(const string& dict, const string& model, const string& userDict = "")
: mixSeg_(dict, model, userDict),
trie_(mixSeg_.GetDictTrie()) {
}
QuerySegment(const DictTrie* dictTrie, const HMMModel* model)
: mixSeg_(dictTrie, model), trie_(dictTrie) {
}
~QuerySegment() {
}
void Cut(const string& sentence, vector<string>& words) const {
Cut(sentence, words, true);
}
void Cut(const string& sentence, vector<string>& words, bool hmm) const {
vector<Word> tmp;
Cut(sentence, tmp, hmm);
GetStringsFromWords(tmp, words);
}
void Cut(const string& sentence, vector<Word>& words, bool hmm = true) const {
PreFilter pre_filter(symbols_, sentence);
PreFilter::Range range;
vector<WordRange> wrs;
wrs.reserve(sentence.size()/2);
while (pre_filter.HasNext()) {
range = pre_filter.Next();
Cut(range.begin, range.end, wrs, hmm);
public:
QuerySegment(const string& dict, const string& model, const string& userDict = "")
: mixSeg_(dict, model, userDict),
trie_(mixSeg_.GetDictTrie()) {
}
words.clear();
words.reserve(wrs.size());
GetWordsFromWordRanges(sentence, wrs, words);
}
void Cut(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end, vector<WordRange>& res, bool hmm) const {
//use mix Cut first
vector<WordRange> mixRes;
mixSeg_.Cut(begin, end, mixRes, hmm);
vector<WordRange> fullRes;
for (vector<WordRange>::const_iterator mixResItr = mixRes.begin(); mixResItr != mixRes.end(); mixResItr++) {
if (mixResItr->Length() > 2) {
for (size_t i = 0; i + 1 < mixResItr->Length(); i++) {
WordRange wr(mixResItr->left + i, mixResItr->left + i + 1);
if (trie_->Find(wr.left, wr.right + 1) != NULL) {
res.push_back(wr);
}
}
}
if (mixResItr->Length() > 3) {
for (size_t i = 0; i + 2 < mixResItr->Length(); i++) {
WordRange wr(mixResItr->left + i, mixResItr->left + i + 2);
if (trie_->Find(wr.left, wr.right + 1) != NULL) {
res.push_back(wr);
}
}
}
res.push_back(*mixResItr);
QuerySegment(const DictTrie* dictTrie, const HMMModel* model)
: mixSeg_(dictTrie, model), trie_(dictTrie) {
}
}
private:
bool IsAllAscii(const Unicode& s) const {
for(size_t i = 0; i < s.size(); i++) {
if (s[i] >= 0x80) {
return false;
}
}
return true;
}
MixSegment mixSeg_;
const DictTrie* trie_;
~QuerySegment() {
}
void Cut(const string& sentence, vector<string>& words) const {
Cut(sentence, words, true);
}
void Cut(const string& sentence, vector<string>& words, bool hmm) const {
vector<Word> tmp;
Cut(sentence, tmp, hmm);
GetStringsFromWords(tmp, words);
}
void Cut(const string& sentence, vector<Word>& words, bool hmm = true) const {
PreFilter pre_filter(symbols_, sentence);
PreFilter::Range range;
vector<WordRange> wrs;
wrs.reserve(sentence.size() / 2);
while(pre_filter.HasNext()) {
range = pre_filter.Next();
Cut(range.begin, range.end, wrs, hmm);
}
words.clear();
words.reserve(wrs.size());
GetWordsFromWordRanges(sentence, wrs, words);
}
void Cut(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end, vector<WordRange>& res, bool hmm) const {
//use mix Cut first
vector<WordRange> mixRes;
mixSeg_.Cut(begin, end, mixRes, hmm);
vector<WordRange> fullRes;
for(vector<WordRange>::const_iterator mixResItr = mixRes.begin(); mixResItr != mixRes.end(); mixResItr++) {
if(mixResItr->Length() > 2) {
for(size_t i = 0; i + 1 < mixResItr->Length(); i++) {
WordRange wr(mixResItr->left + i, mixResItr->left + i + 1);
if(trie_->Find(wr.left, wr.right + 1) != NULL) {
res.push_back(wr);
}
}
}
if(mixResItr->Length() > 3) {
for(size_t i = 0; i + 2 < mixResItr->Length(); i++) {
WordRange wr(mixResItr->left + i, mixResItr->left + i + 2);
if(trie_->Find(wr.left, wr.right + 1) != NULL) {
res.push_back(wr);
}
}
}
res.push_back(*mixResItr);
}
}
private:
bool IsAllAscii(const Unicode& s) const {
for(size_t i = 0; i < s.size(); i++) {
if(s[i] >= 0x80) {
return false;
}
}
return true;
}
MixSegment mixSeg_;
const DictTrie* trie_;
}; // QuerySegment
} // namespace cppjieba

View File

@ -31,32 +31,32 @@ const char* const SPECIAL_SEPARATORS = " \t\n\xEF\xBC\x8C\xE3\x80\x82";
using namespace limonp;
class SegmentBase {
public:
SegmentBase() {
XCHECK(ResetSeparators(SPECIAL_SEPARATORS));
}
virtual ~SegmentBase() {
}
virtual void Cut(const string& sentence, vector<string>& words) const = 0;
bool ResetSeparators(const string& s) {
symbols_.clear();
RuneStrArray runes;
if (!DecodeRunesInString(s, runes)) {
XLOG(ERROR) << "decode " << s << " failed";
return false;
public:
SegmentBase() {
XCHECK(ResetSeparators(SPECIAL_SEPARATORS));
}
for (size_t i = 0; i < runes.size(); i++) {
if (!symbols_.insert(runes[i].rune).second) {
XLOG(ERROR) << s.substr(runes[i].offset, runes[i].len) << " already exists";
return false;
}
virtual ~SegmentBase() {
}
return true;
}
protected:
unordered_set<Rune> symbols_;
virtual void Cut(const string& sentence, vector<string>& words) const = 0;
bool ResetSeparators(const string& s) {
symbols_.clear();
RuneStrArray runes;
if(!DecodeRunesInString(s, runes)) {
XLOG(ERROR) << "decode " << s << " failed";
return false;
}
for(size_t i = 0; i < runes.size(); i++) {
if(!symbols_.insert(runes[i].rune).second) {
XLOG(ERROR) << s.substr(runes[i].offset, runes[i].len) << " already exists";
return false;
}
}
return true;
}
protected:
unordered_set<Rune> symbols_;
}; // class SegmentBase
} // cppjieba

View File

@ -23,16 +23,16 @@
namespace cppjieba {
class SegmentTagged : public SegmentBase{
public:
SegmentTagged() {
}
virtual ~SegmentTagged() {
}
class SegmentTagged : public SegmentBase {
public:
SegmentTagged() {
}
virtual ~SegmentTagged() {
}
virtual bool Tag(const string& src, vector<pair<string, string> >& res) const = 0;
virtual bool Tag(const string& src, vector<pair<string, string> >& res) const = 0;
virtual const DictTrie* GetDictTrie() const = 0;
virtual const DictTrie* GetDictTrie() const = 0;
}; // class SegmentTagged

View File

@ -23,100 +23,104 @@
#include "Jieba.hpp"
namespace cppjieba {
using namespace limonp;
using namespace std;
using namespace limonp;
using namespace std;
class TextRankExtractor {
public:
typedef struct _Word {string word;vector<size_t> offsets;double weight;} Word; // struct Word
private:
typedef std::map<string,Word> WordMap;
class WordGraph{
class TextRankExtractor {
public:
typedef struct _Word {
string word;
vector<size_t> offsets;
double weight;
} Word; // struct Word
private:
typedef std::map<string, Word> WordMap;
class WordGraph {
private:
typedef double Score;
typedef string Node;
typedef std::set<Node> NodeSet;
typedef double Score;
typedef string Node;
typedef std::set<Node> NodeSet;
typedef std::map<Node,double> Edges;
typedef std::map<Node,Edges> Graph;
//typedef std::unordered_map<Node,double> Edges;
//typedef std::unordered_map<Node,Edges> Graph;
typedef std::map<Node, double> Edges;
typedef std::map<Node, Edges> Graph;
//typedef std::unordered_map<Node,double> Edges;
//typedef std::unordered_map<Node,Edges> Graph;
double d;
Graph graph;
NodeSet nodeSet;
double d;
Graph graph;
NodeSet nodeSet;
public:
WordGraph(): d(0.85) {};
WordGraph(double in_d): d(in_d) {};
WordGraph(): d(0.85) {};
WordGraph(double in_d): d(in_d) {};
void addEdge(Node start,Node end,double weight){
Edges temp;
Edges::iterator gotEdges;
nodeSet.insert(start);
nodeSet.insert(end);
graph[start][end]+=weight;
graph[end][start]+=weight;
}
void rank(WordMap &ws,size_t rankTime=10){
WordMap outSum;
Score wsdef, min_rank, max_rank;
if( graph.size() == 0)
return;
wsdef = 1.0 / graph.size();
for(Graph::iterator edges=graph.begin();edges!=graph.end();++edges){
// edges->first start节点edge->first end节点edge->second 权重
ws[edges->first].word=edges->first;
ws[edges->first].weight=wsdef;
outSum[edges->first].weight=0;
for(Edges::iterator edge=edges->second.begin();edge!=edges->second.end();++edge){
outSum[edges->first].weight+=edge->second;
}
}
//sort(nodeSet.begin(),nodeSet.end()); 是否需要排序?
for( size_t i=0; i<rankTime; i++ ){
for(NodeSet::iterator node = nodeSet.begin(); node != nodeSet.end(); node++ ){
double s = 0;
for( Edges::iterator edge= graph[*node].begin(); edge != graph[*node].end(); edge++ )
// edge->first end节点edge->second 权重
s += edge->second / outSum[edge->first].weight * ws[edge->first].weight;
ws[*node].weight = (1 - d) + d * s;
}
void addEdge(Node start, Node end, double weight) {
Edges temp;
Edges::iterator gotEdges;
nodeSet.insert(start);
nodeSet.insert(end);
graph[start][end] += weight;
graph[end][start] += weight;
}
min_rank=max_rank=ws.begin()->second.weight;
for(WordMap::iterator i = ws.begin(); i != ws.end(); i ++){
if( i->second.weight < min_rank ){
min_rank = i->second.weight;
}
if( i->second.weight > max_rank ){
max_rank = i->second.weight;
}
void rank(WordMap &ws, size_t rankTime = 10) {
WordMap outSum;
Score wsdef, min_rank, max_rank;
if(graph.size() == 0)
return;
wsdef = 1.0 / graph.size();
for(Graph::iterator edges = graph.begin(); edges != graph.end(); ++edges) {
// edges->first start节点edge->first end节点edge->second 权重
ws[edges->first].word = edges->first;
ws[edges->first].weight = wsdef;
outSum[edges->first].weight = 0;
for(Edges::iterator edge = edges->second.begin(); edge != edges->second.end(); ++edge) {
outSum[edges->first].weight += edge->second;
}
}
//sort(nodeSet.begin(),nodeSet.end()); 是否需要排序?
for(size_t i = 0; i < rankTime; i++) {
for(NodeSet::iterator node = nodeSet.begin(); node != nodeSet.end(); node++) {
double s = 0;
for(Edges::iterator edge = graph[*node].begin(); edge != graph[*node].end(); edge++)
// edge->first end节点edge->second 权重
s += edge->second / outSum[edge->first].weight * ws[edge->first].weight;
ws[*node].weight = (1 - d) + d * s;
}
}
min_rank = max_rank = ws.begin()->second.weight;
for(WordMap::iterator i = ws.begin(); i != ws.end(); i ++) {
if(i->second.weight < min_rank) {
min_rank = i->second.weight;
}
if(i->second.weight > max_rank) {
max_rank = i->second.weight;
}
}
for(WordMap::iterator i = ws.begin(); i != ws.end(); i ++) {
ws[i->first].weight = (i->second.weight - min_rank / 10.0) / (max_rank - min_rank / 10.0);
}
}
for(WordMap::iterator i = ws.begin(); i != ws.end(); i ++){
ws[i->first].weight = (i->second.weight - min_rank / 10.0) / (max_rank - min_rank / 10.0);
}
}
};
public:
TextRankExtractor(const string& dictPath,
const string& hmmFilePath,
const string& stopWordPath,
const string& userDict = "")
: segment_(dictPath, hmmFilePath, userDict) {
LoadStopWordDict(stopWordPath);
}
TextRankExtractor(const DictTrie* dictTrie,
const HMMModel* model,
const string& stopWordPath)
: segment_(dictTrie, model) {
LoadStopWordDict(stopWordPath);
}
public:
TextRankExtractor(const string& dictPath,
const string& hmmFilePath,
const string& stopWordPath,
const string& userDict = "")
: segment_(dictPath, hmmFilePath, userDict) {
LoadStopWordDict(stopWordPath);
}
TextRankExtractor(const DictTrie* dictTrie,
const HMMModel* model,
const string& stopWordPath)
: segment_(dictTrie, model) {
LoadStopWordDict(stopWordPath);
}
TextRankExtractor(const Jieba& jieba, const string& stopWordPath) : segment_(jieba.GetDictTrie(), jieba.GetHMMModel()) {
LoadStopWordDict(stopWordPath);
}
@ -124,83 +128,83 @@ namespace cppjieba {
}
void Extract(const string& sentence, vector<string>& keywords, size_t topN) const {
vector<Word> topWords;
Extract(sentence, topWords, topN);
for (size_t i = 0; i < topWords.size(); i++) {
keywords.push_back(topWords[i].word);
}
vector<Word> topWords;
Extract(sentence, topWords, topN);
for(size_t i = 0; i < topWords.size(); i++) {
keywords.push_back(topWords[i].word);
}
}
void Extract(const string& sentence, vector<pair<string, double> >& keywords, size_t topN) const {
vector<Word> topWords;
Extract(sentence, topWords, topN);
for (size_t i = 0; i < topWords.size(); i++) {
keywords.push_back(pair<string, double>(topWords[i].word, topWords[i].weight));
}
vector<Word> topWords;
Extract(sentence, topWords, topN);
for(size_t i = 0; i < topWords.size(); i++) {
keywords.push_back(pair<string, double>(topWords[i].word, topWords[i].weight));
}
}
void Extract(const string& sentence, vector<Word>& keywords, size_t topN, size_t span=5,size_t rankTime=10) const {
vector<string> words;
segment_.Cut(sentence, words);
void Extract(const string& sentence, vector<Word>& keywords, size_t topN, size_t span = 5, size_t rankTime = 10) const {
vector<string> words;
segment_.Cut(sentence, words);
TextRankExtractor::WordGraph graph;
WordMap wordmap;
size_t offset = 0;
TextRankExtractor::WordGraph graph;
WordMap wordmap;
size_t offset = 0;
for(size_t i=0; i < words.size(); i++){
size_t t = offset;
offset += words[i].size();
if (IsSingleWord(words[i]) || stopWords_.find(words[i]) != stopWords_.end()) {
continue;
for(size_t i = 0; i < words.size(); i++) {
size_t t = offset;
offset += words[i].size();
if(IsSingleWord(words[i]) || stopWords_.find(words[i]) != stopWords_.end()) {
continue;
}
for(size_t j = i + 1, skip = 0; j < i + span + skip && j < words.size(); j++) {
if(IsSingleWord(words[j]) || stopWords_.find(words[j]) != stopWords_.end()) {
skip++;
continue;
}
graph.addEdge(words[i], words[j], 1);
}
wordmap[words[i]].offsets.push_back(t);
}
for(size_t j=i+1,skip=0;j<i+span+skip && j<words.size();j++){
if (IsSingleWord(words[j]) || stopWords_.find(words[j]) != stopWords_.end()) {
skip++;
continue;
}
graph.addEdge(words[i],words[j],1);
if(offset != sentence.size()) {
XLOG(ERROR) << "words illegal";
return;
}
wordmap[words[i]].offsets.push_back(t);
}
if (offset != sentence.size()) {
XLOG(ERROR) << "words illegal";
return;
}
graph.rank(wordmap,rankTime);
keywords.clear();
keywords.reserve(wordmap.size());
for (WordMap::iterator itr = wordmap.begin(); itr != wordmap.end(); ++itr) {
keywords.push_back(itr->second);
}
topN = min(topN, keywords.size());
partial_sort(keywords.begin(), keywords.begin() + topN, keywords.end(), Compare);
keywords.resize(topN);
graph.rank(wordmap, rankTime);
keywords.clear();
keywords.reserve(wordmap.size());
for(WordMap::iterator itr = wordmap.begin(); itr != wordmap.end(); ++itr) {
keywords.push_back(itr->second);
}
topN = min(topN, keywords.size());
partial_sort(keywords.begin(), keywords.begin() + topN, keywords.end(), Compare);
keywords.resize(topN);
}
private:
private:
void LoadStopWordDict(const string& filePath) {
ifstream ifs(filePath.c_str());
XCHECK(ifs.is_open()) << "open " << filePath << " failed";
string line ;
while (getline(ifs, line)) {
stopWords_.insert(line);
}
assert(stopWords_.size());
ifstream ifs(filePath.c_str());
XCHECK(ifs.is_open()) << "open " << filePath << " failed";
string line ;
while(getline(ifs, line)) {
stopWords_.insert(line);
}
assert(stopWords_.size());
}
static bool Compare(const Word &x,const Word &y){
return x.weight > y.weight;
static bool Compare(const Word &x, const Word &y) {
return x.weight > y.weight;
}
MixSegment segment_;
unordered_set<string> stopWords_;
}; // class TextRankExtractor
inline ostream& operator << (ostream& os, const TextRankExtractor::Word& word) {
return os << "{\"word\": \"" << word.word << "\", \"offset\": " << word.offsets << ", \"weight\": " << word.weight << "}";
}
}; // class TextRankExtractor
inline ostream& operator << (ostream& os, const TextRankExtractor::Word& word) {
return os << "{\"word\": \"" << word.word << "\", \"offset\": " << word.offsets << ", \"weight\": " << word.weight << "}";
}
} // namespace cppjieba
#endif

View File

@ -31,9 +31,9 @@ using namespace std;
const size_t MAX_WORD_LENGTH = 512;
struct DictUnit {
Unicode word;
double weight;
string tag;
Unicode word;
double weight;
string tag;
}; // struct DictUnit
// for debugging
@ -44,148 +44,148 @@ struct DictUnit {
// }
struct Dag {
RuneStr runestr;
// [offset, nexts.first]
limonp::LocalVector<pair<size_t, const DictUnit*> > nexts;
const DictUnit * pInfo;
double weight;
size_t nextPos; // TODO
Dag():runestr(), pInfo(NULL), weight(0.0), nextPos(0) {
}
RuneStr runestr;
// [offset, nexts.first]
limonp::LocalVector<pair<size_t, const DictUnit*> > nexts;
const DictUnit * pInfo;
double weight;
size_t nextPos; // TODO
Dag(): runestr(), pInfo(NULL), weight(0.0), nextPos(0) {
}
}; // struct Dag
typedef Rune TrieKey;
class TrieNode {
public :
TrieNode(): next(NULL), ptValue(NULL) {
}
public:
typedef unordered_map<TrieKey, TrieNode*> NextMap;
NextMap *next;
const DictUnit *ptValue;
public :
TrieNode(): next(NULL), ptValue(NULL) {
}
public:
typedef unordered_map<TrieKey, TrieNode*> NextMap;
NextMap *next;
const DictUnit *ptValue;
};
class Trie {
public:
Trie(const vector<Unicode>& keys, const vector<const DictUnit*>& valuePointers)
: root_(new TrieNode) {
CreateTrie(keys, valuePointers);
}
~Trie() {
DeleteNode(root_);
}
const DictUnit* Find(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end) const {
if (begin == end) {
return NULL;
public:
Trie(const vector<Unicode>& keys, const vector<const DictUnit*>& valuePointers)
: root_(new TrieNode) {
CreateTrie(keys, valuePointers);
}
~Trie() {
DeleteNode(root_);
}
const TrieNode* ptNode = root_;
TrieNode::NextMap::const_iterator citer;
for (RuneStrArray::const_iterator it = begin; it != end; it++) {
if (NULL == ptNode->next) {
return NULL;
}
citer = ptNode->next->find(it->rune);
if (ptNode->next->end() == citer) {
return NULL;
}
ptNode = citer->second;
}
return ptNode->ptValue;
}
void Find(RuneStrArray::const_iterator begin,
RuneStrArray::const_iterator end,
vector<struct Dag>&res,
size_t max_word_len = MAX_WORD_LENGTH) const {
assert(root_ != NULL);
res.resize(end - begin);
const TrieNode *ptNode = NULL;
TrieNode::NextMap::const_iterator citer;
for (size_t i = 0; i < size_t(end - begin); i++) {
res[i].runestr = *(begin + i);
if (root_->next != NULL && root_->next->end() != (citer = root_->next->find(res[i].runestr.rune))) {
ptNode = citer->second;
} else {
ptNode = NULL;
}
if (ptNode != NULL) {
res[i].nexts.push_back(pair<size_t, const DictUnit*>(i, ptNode->ptValue));
} else {
res[i].nexts.push_back(pair<size_t, const DictUnit*>(i, static_cast<const DictUnit*>(NULL)));
}
for (size_t j = i + 1; j < size_t(end - begin) && (j - i + 1) <= max_word_len; j++) {
if (ptNode == NULL || ptNode->next == NULL) {
break;
const DictUnit* Find(RuneStrArray::const_iterator begin, RuneStrArray::const_iterator end) const {
if(begin == end) {
return NULL;
}
citer = ptNode->next->find((begin + j)->rune);
if (ptNode->next->end() == citer) {
break;
const TrieNode* ptNode = root_;
TrieNode::NextMap::const_iterator citer;
for(RuneStrArray::const_iterator it = begin; it != end; it++) {
if(NULL == ptNode->next) {
return NULL;
}
citer = ptNode->next->find(it->rune);
if(ptNode->next->end() == citer) {
return NULL;
}
ptNode = citer->second;
}
ptNode = citer->second;
if (NULL != ptNode->ptValue) {
res[i].nexts.push_back(pair<size_t, const DictUnit*>(j, ptNode->ptValue));
return ptNode->ptValue;
}
void Find(RuneStrArray::const_iterator begin,
RuneStrArray::const_iterator end,
vector<struct Dag>&res,
size_t max_word_len = MAX_WORD_LENGTH) const {
assert(root_ != NULL);
res.resize(end - begin);
const TrieNode *ptNode = NULL;
TrieNode::NextMap::const_iterator citer;
for(size_t i = 0; i < size_t(end - begin); i++) {
res[i].runestr = *(begin + i);
if(root_->next != NULL && root_->next->end() != (citer = root_->next->find(res[i].runestr.rune))) {
ptNode = citer->second;
} else {
ptNode = NULL;
}
if(ptNode != NULL) {
res[i].nexts.push_back(pair<size_t, const DictUnit*>(i, ptNode->ptValue));
} else {
res[i].nexts.push_back(pair<size_t, const DictUnit*>(i, static_cast<const DictUnit*>(NULL)));
}
for(size_t j = i + 1; j < size_t(end - begin) && (j - i + 1) <= max_word_len; j++) {
if(ptNode == NULL || ptNode->next == NULL) {
break;
}
citer = ptNode->next->find((begin + j)->rune);
if(ptNode->next->end() == citer) {
break;
}
ptNode = citer->second;
if(NULL != ptNode->ptValue) {
res[i].nexts.push_back(pair<size_t, const DictUnit*>(j, ptNode->ptValue));
}
}
}
}
}
}
void InsertNode(const Unicode& key, const DictUnit* ptValue) {
if (key.begin() == key.end()) {
return;
}
TrieNode::NextMap::const_iterator kmIter;
TrieNode *ptNode = root_;
for (Unicode::const_iterator citer = key.begin(); citer != key.end(); ++citer) {
if (NULL == ptNode->next) {
ptNode->next = new TrieNode::NextMap;
}
kmIter = ptNode->next->find(*citer);
if (ptNode->next->end() == kmIter) {
TrieNode *nextNode = new TrieNode;
void InsertNode(const Unicode& key, const DictUnit* ptValue) {
if(key.begin() == key.end()) {
return;
}
ptNode->next->insert(make_pair(*citer, nextNode));
ptNode = nextNode;
} else {
ptNode = kmIter->second;
}
}
assert(ptNode != NULL);
ptNode->ptValue = ptValue;
}
TrieNode::NextMap::const_iterator kmIter;
TrieNode *ptNode = root_;
for(Unicode::const_iterator citer = key.begin(); citer != key.end(); ++citer) {
if(NULL == ptNode->next) {
ptNode->next = new TrieNode::NextMap;
}
kmIter = ptNode->next->find(*citer);
if(ptNode->next->end() == kmIter) {
TrieNode *nextNode = new TrieNode;
private:
void CreateTrie(const vector<Unicode>& keys, const vector<const DictUnit*>& valuePointers) {
if (valuePointers.empty() || keys.empty()) {
return;
ptNode->next->insert(make_pair(*citer, nextNode));
ptNode = nextNode;
} else {
ptNode = kmIter->second;
}
}
assert(ptNode != NULL);
ptNode->ptValue = ptValue;
}
assert(keys.size() == valuePointers.size());
for (size_t i = 0; i < keys.size(); i++) {
InsertNode(keys[i], valuePointers[i]);
}
}
private:
void CreateTrie(const vector<Unicode>& keys, const vector<const DictUnit*>& valuePointers) {
if(valuePointers.empty() || keys.empty()) {
return;
}
assert(keys.size() == valuePointers.size());
void DeleteNode(TrieNode* node) {
if (NULL == node) {
return;
for(size_t i = 0; i < keys.size(); i++) {
InsertNode(keys[i], valuePointers[i]);
}
}
if (NULL != node->next) {
for (TrieNode::NextMap::iterator it = node->next->begin(); it != node->next->end(); ++it) {
DeleteNode(it->second);
}
delete node->next;
}
delete node;
}
TrieNode* root_;
void DeleteNode(TrieNode* node) {
if(NULL == node) {
return;
}
if(NULL != node->next) {
for(TrieNode::NextMap::iterator it = node->next->begin(); it != node->next->end(); ++it) {
DeleteNode(it->second);
}
delete node->next;
}
delete node;
}
TrieNode* root_;
}; // class Trie
} // namespace cppjieba

View File

@ -34,40 +34,40 @@ using std::vector;
typedef uint32_t Rune;
struct Word {
string word;
uint32_t offset;
uint32_t unicode_offset;
uint32_t unicode_length;
Word(const string& w, uint32_t o)
: word(w), offset(o) {
}
Word(const string& w, uint32_t o, uint32_t unicode_offset, uint32_t unicode_length)
: word(w), offset(o), unicode_offset(unicode_offset), unicode_length(unicode_length) {
}
string word;
uint32_t offset;
uint32_t unicode_offset;
uint32_t unicode_length;
Word(const string& w, uint32_t o)
: word(w), offset(o) {
}
Word(const string& w, uint32_t o, uint32_t unicode_offset, uint32_t unicode_length)
: word(w), offset(o), unicode_offset(unicode_offset), unicode_length(unicode_length) {
}
}; // struct Word
inline std::ostream& operator << (std::ostream& os, const Word& w) {
return os << "{\"word\": \"" << w.word << "\", \"offset\": " << w.offset << "}";
return os << "{\"word\": \"" << w.word << "\", \"offset\": " << w.offset << "}";
}
struct RuneStr {
Rune rune;
uint32_t offset;
uint32_t len;
uint32_t unicode_offset;
uint32_t unicode_length;
RuneStr(): rune(0), offset(0), len(0), unicode_offset(0), unicode_length(0) {
}
RuneStr(Rune r, uint32_t o, uint32_t l)
: rune(r), offset(o), len(l), unicode_offset(0), unicode_length(0) {
}
RuneStr(Rune r, uint32_t o, uint32_t l, uint32_t unicode_offset, uint32_t unicode_length)
: rune(r), offset(o), len(l), unicode_offset(unicode_offset), unicode_length(unicode_length) {
}
Rune rune;
uint32_t offset;
uint32_t len;
uint32_t unicode_offset;
uint32_t unicode_length;
RuneStr(): rune(0), offset(0), len(0), unicode_offset(0), unicode_length(0) {
}
RuneStr(Rune r, uint32_t o, uint32_t l)
: rune(r), offset(o), len(l), unicode_offset(0), unicode_length(0) {
}
RuneStr(Rune r, uint32_t o, uint32_t l, uint32_t unicode_offset, uint32_t unicode_length)
: rune(r), offset(o), len(l), unicode_offset(unicode_offset), unicode_length(unicode_length) {
}
}; // struct RuneStr
inline std::ostream& operator << (std::ostream& os, const RuneStr& r) {
return os << "{\"rune\": \"" << r.rune << "\", \"offset\": " << r.offset << ", \"len\": " << r.len << "}";
return os << "{\"rune\": \"" << r.rune << "\", \"offset\": " << r.offset << ", \"len\": " << r.len << "}";
}
typedef limonp::LocalVector<Rune> Unicode;
@ -75,169 +75,169 @@ typedef limonp::LocalVector<struct RuneStr> RuneStrArray;
// [left, right]
struct WordRange {
RuneStrArray::const_iterator left;
RuneStrArray::const_iterator right;
WordRange(RuneStrArray::const_iterator l, RuneStrArray::const_iterator r)
: left(l), right(r) {
}
size_t Length() const {
return right - left + 1;
}
bool IsAllAscii() const {
for (RuneStrArray::const_iterator iter = left; iter <= right; ++iter) {
if (iter->rune >= 0x80) {
return false;
}
RuneStrArray::const_iterator left;
RuneStrArray::const_iterator right;
WordRange(RuneStrArray::const_iterator l, RuneStrArray::const_iterator r)
: left(l), right(r) {
}
size_t Length() const {
return right - left + 1;
}
bool IsAllAscii() const {
for(RuneStrArray::const_iterator iter = left; iter <= right; ++iter) {
if(iter->rune >= 0x80) {
return false;
}
}
return true;
}
return true;
}
}; // struct WordRange
struct RuneStrLite {
uint32_t rune;
uint32_t len;
RuneStrLite(): rune(0), len(0) {
}
RuneStrLite(uint32_t r, uint32_t l): rune(r), len(l) {
}
uint32_t rune;
uint32_t len;
RuneStrLite(): rune(0), len(0) {
}
RuneStrLite(uint32_t r, uint32_t l): rune(r), len(l) {
}
}; // struct RuneStrLite
inline RuneStrLite DecodeRuneInString(const char* str, size_t len) {
RuneStrLite rp(0, 0);
if (str == NULL || len == 0) {
RuneStrLite rp(0, 0);
if(str == NULL || len == 0) {
return rp;
}
if(!(str[0] & 0x80)) { // 0xxxxxxx
// 7bit, total 7bit
rp.rune = (uint8_t)(str[0]) & 0x7f;
rp.len = 1;
} else if((uint8_t)str[0] <= 0xdf && 1 < len) {
// 110xxxxxx
// 5bit, total 5bit
rp.rune = (uint8_t)(str[0]) & 0x1f;
// 6bit, total 11bit
rp.rune <<= 6;
rp.rune |= (uint8_t)(str[1]) & 0x3f;
rp.len = 2;
} else if((uint8_t)str[0] <= 0xef && 2 < len) { // 1110xxxxxx
// 4bit, total 4bit
rp.rune = (uint8_t)(str[0]) & 0x0f;
// 6bit, total 10bit
rp.rune <<= 6;
rp.rune |= (uint8_t)(str[1]) & 0x3f;
// 6bit, total 16bit
rp.rune <<= 6;
rp.rune |= (uint8_t)(str[2]) & 0x3f;
rp.len = 3;
} else if((uint8_t)str[0] <= 0xf7 && 3 < len) { // 11110xxxx
// 3bit, total 3bit
rp.rune = (uint8_t)(str[0]) & 0x07;
// 6bit, total 9bit
rp.rune <<= 6;
rp.rune |= (uint8_t)(str[1]) & 0x3f;
// 6bit, total 15bit
rp.rune <<= 6;
rp.rune |= (uint8_t)(str[2]) & 0x3f;
// 6bit, total 21bit
rp.rune <<= 6;
rp.rune |= (uint8_t)(str[3]) & 0x3f;
rp.len = 4;
} else {
rp.rune = 0;
rp.len = 0;
}
return rp;
}
if (!(str[0] & 0x80)) { // 0xxxxxxx
// 7bit, total 7bit
rp.rune = (uint8_t)(str[0]) & 0x7f;
rp.len = 1;
} else if ((uint8_t)str[0] <= 0xdf && 1 < len) {
// 110xxxxxx
// 5bit, total 5bit
rp.rune = (uint8_t)(str[0]) & 0x1f;
// 6bit, total 11bit
rp.rune <<= 6;
rp.rune |= (uint8_t)(str[1]) & 0x3f;
rp.len = 2;
} else if((uint8_t)str[0] <= 0xef && 2 < len) { // 1110xxxxxx
// 4bit, total 4bit
rp.rune = (uint8_t)(str[0]) & 0x0f;
// 6bit, total 10bit
rp.rune <<= 6;
rp.rune |= (uint8_t)(str[1]) & 0x3f;
// 6bit, total 16bit
rp.rune <<= 6;
rp.rune |= (uint8_t)(str[2]) & 0x3f;
rp.len = 3;
} else if((uint8_t)str[0] <= 0xf7 && 3 < len) { // 11110xxxx
// 3bit, total 3bit
rp.rune = (uint8_t)(str[0]) & 0x07;
// 6bit, total 9bit
rp.rune <<= 6;
rp.rune |= (uint8_t)(str[1]) & 0x3f;
// 6bit, total 15bit
rp.rune <<= 6;
rp.rune |= (uint8_t)(str[2]) & 0x3f;
// 6bit, total 21bit
rp.rune <<= 6;
rp.rune |= (uint8_t)(str[3]) & 0x3f;
rp.len = 4;
} else {
rp.rune = 0;
rp.len = 0;
}
return rp;
}
inline bool DecodeRunesInString(const char* s, size_t len, RuneStrArray& runes) {
runes.clear();
runes.reserve(len / 2);
for (uint32_t i = 0, j = 0; i < len;) {
RuneStrLite rp = DecodeRuneInString(s + i, len - i);
if (rp.len == 0) {
runes.clear();
return false;
runes.clear();
runes.reserve(len / 2);
for(uint32_t i = 0, j = 0; i < len;) {
RuneStrLite rp = DecodeRuneInString(s + i, len - i);
if(rp.len == 0) {
runes.clear();
return false;
}
RuneStr x(rp.rune, i, rp.len, j, 1);
runes.push_back(x);
i += rp.len;
++j;
}
RuneStr x(rp.rune, i, rp.len, j, 1);
runes.push_back(x);
i += rp.len;
++j;
}
return true;
return true;
}
inline bool DecodeRunesInString(const string& s, RuneStrArray& runes) {
return DecodeRunesInString(s.c_str(), s.size(), runes);
return DecodeRunesInString(s.c_str(), s.size(), runes);
}
inline bool DecodeRunesInString(const char* s, size_t len, Unicode& unicode) {
unicode.clear();
RuneStrArray runes;
if (!DecodeRunesInString(s, len, runes)) {
return false;
}
unicode.reserve(runes.size());
for (size_t i = 0; i < runes.size(); i++) {
unicode.push_back(runes[i].rune);
}
return true;
unicode.clear();
RuneStrArray runes;
if(!DecodeRunesInString(s, len, runes)) {
return false;
}
unicode.reserve(runes.size());
for(size_t i = 0; i < runes.size(); i++) {
unicode.push_back(runes[i].rune);
}
return true;
}
inline bool IsSingleWord(const string& str) {
RuneStrLite rp = DecodeRuneInString(str.c_str(), str.size());
return rp.len == str.size();
RuneStrLite rp = DecodeRuneInString(str.c_str(), str.size());
return rp.len == str.size();
}
inline bool DecodeRunesInString(const string& s, Unicode& unicode) {
return DecodeRunesInString(s.c_str(), s.size(), unicode);
return DecodeRunesInString(s.c_str(), s.size(), unicode);
}
inline Unicode DecodeRunesInString(const string& s) {
Unicode result;
DecodeRunesInString(s, result);
return result;
Unicode result;
DecodeRunesInString(s, result);
return result;
}
// [left, right]
inline Word GetWordFromRunes(const string& s, RuneStrArray::const_iterator left, RuneStrArray::const_iterator right) {
assert(right->offset >= left->offset);
uint32_t len = right->offset - left->offset + right->len;
uint32_t unicode_length = right->unicode_offset - left->unicode_offset + right->unicode_length;
return Word(s.substr(left->offset, len), left->offset, left->unicode_offset, unicode_length);
assert(right->offset >= left->offset);
uint32_t len = right->offset - left->offset + right->len;
uint32_t unicode_length = right->unicode_offset - left->unicode_offset + right->unicode_length;
return Word(s.substr(left->offset, len), left->offset, left->unicode_offset, unicode_length);
}
inline string GetStringFromRunes(const string& s, RuneStrArray::const_iterator left, RuneStrArray::const_iterator right) {
assert(right->offset >= left->offset);
uint32_t len = right->offset - left->offset + right->len;
return s.substr(left->offset, len);
assert(right->offset >= left->offset);
uint32_t len = right->offset - left->offset + right->len;
return s.substr(left->offset, len);
}
inline void GetWordsFromWordRanges(const string& s, const vector<WordRange>& wrs, vector<Word>& words) {
for (size_t i = 0; i < wrs.size(); i++) {
words.push_back(GetWordFromRunes(s, wrs[i].left, wrs[i].right));
}
for(size_t i = 0; i < wrs.size(); i++) {
words.push_back(GetWordFromRunes(s, wrs[i].left, wrs[i].right));
}
}
inline vector<Word> GetWordsFromWordRanges(const string& s, const vector<WordRange>& wrs) {
vector<Word> result;
GetWordsFromWordRanges(s, wrs, result);
return result;
vector<Word> result;
GetWordsFromWordRanges(s, wrs, result);
return result;
}
inline void GetStringsFromWords(const vector<Word>& words, vector<string>& strs) {
strs.resize(words.size());
for (size_t i = 0; i < words.size(); ++i) {
strs[i] = words[i].word;
}
strs.resize(words.size());
for(size_t i = 0; i < words.size(); ++i) {
strs[i] = words[i].word;
}
}
} // namespace cppjieba

View File

@ -33,54 +33,54 @@ namespace limonp {
using namespace std;
class ArgvContext {
public :
ArgvContext(int argc, const char* const * argv) {
for(int i = 0; i < argc; i++) {
if(StartsWith(argv[i], "-")) {
if(i + 1 < argc && !StartsWith(argv[i + 1], "-")) {
mpss_[argv[i]] = argv[i+1];
i++;
} else {
sset_.insert(argv[i]);
public :
ArgvContext(int argc, const char* const * argv) {
for(int i = 0; i < argc; i++) {
if(StartsWith(argv[i], "-")) {
if(i + 1 < argc && !StartsWith(argv[i + 1], "-")) {
mpss_[argv[i]] = argv[i + 1];
i++;
} else {
sset_.insert(argv[i]);
}
} else {
args_.push_back(argv[i]);
}
}
} else {
args_.push_back(argv[i]);
}
}
}
~ArgvContext() {
}
~ArgvContext() {
}
friend ostream& operator << (ostream& os, const ArgvContext& args);
string operator [](size_t i) const {
if(i < args_.size()) {
return args_[i];
friend ostream& operator << (ostream& os, const ArgvContext& args);
string operator [](size_t i) const {
if(i < args_.size()) {
return args_[i];
}
return "";
}
return "";
}
string operator [](const string& key) const {
map<string, string>::const_iterator it = mpss_.find(key);
if(it != mpss_.end()) {
return it->second;
string operator [](const string& key) const {
map<string, string>::const_iterator it = mpss_.find(key);
if(it != mpss_.end()) {
return it->second;
}
return "";
}
return "";
}
bool HasKey(const string& key) const {
if(mpss_.find(key) != mpss_.end() || sset_.find(key) != sset_.end()) {
return true;
bool HasKey(const string& key) const {
if(mpss_.find(key) != mpss_.end() || sset_.find(key) != sset_.end()) {
return true;
}
return false;
}
return false;
}
private:
vector<string> args_;
map<string, string> mpss_;
set<string> sset_;
private:
vector<string> args_;
map<string, string> mpss_;
set<string> sset_;
}; // class ArgvContext
inline ostream& operator << (ostream& os, const ArgvContext& args) {
return os<<args.args_<<args.mpss_<<args.sset_;
return os << args.args_ << args.mpss_ << args.sset_;
}
} // namespace limonp

View File

@ -25,41 +25,41 @@
namespace limonp {
template<class T>
class BlockingQueue: NonCopyable {
public:
BlockingQueue()
: mutex_(), notEmpty_(mutex_), queue_() {
}
void Push(const T& x) {
MutexLockGuard lock(mutex_);
queue_.push(x);
notEmpty_.Notify(); // Wait morphing saves us
}
T Pop() {
MutexLockGuard lock(mutex_);
// always use a while-loop, due to spurious wakeup
while (queue_.empty()) {
notEmpty_.Wait();
public:
BlockingQueue()
: mutex_(), notEmpty_(mutex_), queue_() {
}
assert(!queue_.empty());
T front(queue_.front());
queue_.pop();
return front;
}
size_t Size() const {
MutexLockGuard lock(mutex_);
return queue_.size();
}
bool Empty() const {
return Size() == 0;
}
void Push(const T& x) {
MutexLockGuard lock(mutex_);
queue_.push(x);
notEmpty_.Notify(); // Wait morphing saves us
}
private:
mutable MutexLock mutex_;
Condition notEmpty_;
std::queue<T> queue_;
T Pop() {
MutexLockGuard lock(mutex_);
// always use a while-loop, due to spurious wakeup
while(queue_.empty()) {
notEmpty_.Wait();
}
assert(!queue_.empty());
T front(queue_.front());
queue_.pop();
return front;
}
size_t Size() const {
MutexLockGuard lock(mutex_);
return queue_.size();
}
bool Empty() const {
return Size() == 0;
}
private:
mutable MutexLock mutex_;
Condition notEmpty_;
std::queue<T> queue_;
}; // class BlockingQueue
} // namespace limonp

View File

@ -25,59 +25,59 @@ namespace limonp {
template<typename T>
class BoundedBlockingQueue : NonCopyable {
public:
explicit BoundedBlockingQueue(size_t maxSize)
: mutex_(),
notEmpty_(mutex_),
notFull_(mutex_),
queue_(maxSize) {
}
void Push(const T& x) {
MutexLockGuard lock(mutex_);
while (queue_.Full()) {
notFull_.Wait();
public:
explicit BoundedBlockingQueue(size_t maxSize)
: mutex_(),
notEmpty_(mutex_),
notFull_(mutex_),
queue_(maxSize) {
}
assert(!queue_.Full());
queue_.Push(x);
notEmpty_.Notify();
}
T Pop() {
MutexLockGuard lock(mutex_);
while (queue_.Empty()) {
notEmpty_.Wait();
void Push(const T& x) {
MutexLockGuard lock(mutex_);
while(queue_.Full()) {
notFull_.Wait();
}
assert(!queue_.Full());
queue_.Push(x);
notEmpty_.Notify();
}
assert(!queue_.Empty());
T res = queue_.Pop();
notFull_.Notify();
return res;
}
bool Empty() const {
MutexLockGuard lock(mutex_);
return queue_.Empty();
}
T Pop() {
MutexLockGuard lock(mutex_);
while(queue_.Empty()) {
notEmpty_.Wait();
}
assert(!queue_.Empty());
T res = queue_.Pop();
notFull_.Notify();
return res;
}
bool Full() const {
MutexLockGuard lock(mutex_);
return queue_.Full();
}
bool Empty() const {
MutexLockGuard lock(mutex_);
return queue_.Empty();
}
size_t size() const {
MutexLockGuard lock(mutex_);
return queue_.size();
}
bool Full() const {
MutexLockGuard lock(mutex_);
return queue_.Full();
}
size_t capacity() const {
return queue_.capacity();
}
size_t size() const {
MutexLockGuard lock(mutex_);
return queue_.size();
}
private:
mutable MutexLock mutex_;
Condition notEmpty_;
Condition notFull_;
BoundedQueue<T> queue_;
size_t capacity() const {
return queue_.capacity();
}
private:
mutable MutexLock mutex_;
Condition notEmpty_;
Condition notFull_;
BoundedQueue<T> queue_;
}; // class BoundedBlockingQueue
} // namespace limonp

View File

@ -27,55 +27,55 @@ namespace limonp {
using namespace std;
template<class T>
class BoundedQueue {
public:
explicit BoundedQueue(size_t capacity): capacity_(capacity), circular_buffer_(capacity) {
head_ = 0;
tail_ = 0;
size_ = 0;
assert(capacity_);
}
~BoundedQueue() {
}
public:
explicit BoundedQueue(size_t capacity): capacity_(capacity), circular_buffer_(capacity) {
head_ = 0;
tail_ = 0;
size_ = 0;
assert(capacity_);
}
~BoundedQueue() {
}
void Clear() {
head_ = 0;
tail_ = 0;
size_ = 0;
}
bool Empty() const {
return !size_;
}
bool Full() const {
return capacity_ == size_;
}
size_t Size() const {
return size_;
}
size_t Capacity() const {
return capacity_;
}
void Clear() {
head_ = 0;
tail_ = 0;
size_ = 0;
}
bool Empty() const {
return !size_;
}
bool Full() const {
return capacity_ == size_;
}
size_t Size() const {
return size_;
}
size_t Capacity() const {
return capacity_;
}
void Push(const T& t) {
assert(!Full());
circular_buffer_[tail_] = t;
tail_ = (tail_ + 1) % capacity_;
size_ ++;
}
void Push(const T& t) {
assert(!Full());
circular_buffer_[tail_] = t;
tail_ = (tail_ + 1) % capacity_;
size_ ++;
}
T Pop() {
assert(!Empty());
size_t oldPos = head_;
head_ = (head_ + 1) % capacity_;
size_ --;
return circular_buffer_[oldPos];
}
T Pop() {
assert(!Empty());
size_t oldPos = head_;
head_ = (head_ + 1) % capacity_;
size_ --;
return circular_buffer_[oldPos];
}
private:
size_t head_;
size_t tail_;
size_t size_;
const size_t capacity_;
vector<T> circular_buffer_;
private:
size_t head_;
size_t tail_;
size_t size_;
const size_t capacity_;
vector<T> circular_buffer_;
}; // class BoundedQueue
} // namespace limonp

View File

@ -22,201 +22,201 @@
namespace limonp {
class ClosureInterface {
public:
virtual ~ClosureInterface() {
}
virtual void Run() = 0;
public:
virtual ~ClosureInterface() {
}
virtual void Run() = 0;
};
template <class Funct>
class Closure0: public ClosureInterface {
public:
Closure0(Funct fun) {
fun_ = fun;
}
virtual ~Closure0() {
}
virtual void Run() {
(*fun_)();
}
private:
Funct fun_;
};
public:
Closure0(Funct fun) {
fun_ = fun;
}
virtual ~Closure0() {
}
virtual void Run() {
(*fun_)();
}
private:
Funct fun_;
};
template <class Funct, class Arg1>
class Closure1: public ClosureInterface {
public:
Closure1(Funct fun, Arg1 arg1) {
fun_ = fun;
arg1_ = arg1;
}
virtual ~Closure1() {
}
virtual void Run() {
(*fun_)(arg1_);
}
private:
Funct fun_;
Arg1 arg1_;
};
public:
Closure1(Funct fun, Arg1 arg1) {
fun_ = fun;
arg1_ = arg1;
}
virtual ~Closure1() {
}
virtual void Run() {
(*fun_)(arg1_);
}
private:
Funct fun_;
Arg1 arg1_;
};
template <class Funct, class Arg1, class Arg2>
class Closure2: public ClosureInterface {
public:
Closure2(Funct fun, Arg1 arg1, Arg2 arg2) {
fun_ = fun;
arg1_ = arg1;
arg2_ = arg2;
}
virtual ~Closure2() {
}
virtual void Run() {
(*fun_)(arg1_, arg2_);
}
private:
Funct fun_;
Arg1 arg1_;
Arg2 arg2_;
};
public:
Closure2(Funct fun, Arg1 arg1, Arg2 arg2) {
fun_ = fun;
arg1_ = arg1;
arg2_ = arg2;
}
virtual ~Closure2() {
}
virtual void Run() {
(*fun_)(arg1_, arg2_);
}
private:
Funct fun_;
Arg1 arg1_;
Arg2 arg2_;
};
template <class Funct, class Arg1, class Arg2, class Arg3>
class Closure3: public ClosureInterface {
public:
Closure3(Funct fun, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
fun_ = fun;
arg1_ = arg1;
arg2_ = arg2;
arg3_ = arg3;
}
virtual ~Closure3() {
}
virtual void Run() {
(*fun_)(arg1_, arg2_, arg3_);
}
private:
Funct fun_;
Arg1 arg1_;
Arg2 arg2_;
Arg3 arg3_;
};
public:
Closure3(Funct fun, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
fun_ = fun;
arg1_ = arg1;
arg2_ = arg2;
arg3_ = arg3;
}
virtual ~Closure3() {
}
virtual void Run() {
(*fun_)(arg1_, arg2_, arg3_);
}
private:
Funct fun_;
Arg1 arg1_;
Arg2 arg2_;
Arg3 arg3_;
};
template <class Obj, class Funct>
template <class Obj, class Funct>
class ObjClosure0: public ClosureInterface {
public:
ObjClosure0(Obj* p, Funct fun) {
p_ = p;
fun_ = fun;
}
virtual ~ObjClosure0() {
}
virtual void Run() {
(p_->*fun_)();
}
private:
Obj* p_;
Funct fun_;
};
public:
ObjClosure0(Obj* p, Funct fun) {
p_ = p;
fun_ = fun;
}
virtual ~ObjClosure0() {
}
virtual void Run() {
(p_->*fun_)();
}
private:
Obj* p_;
Funct fun_;
};
template <class Obj, class Funct, class Arg1>
template <class Obj, class Funct, class Arg1>
class ObjClosure1: public ClosureInterface {
public:
ObjClosure1(Obj* p, Funct fun, Arg1 arg1) {
p_ = p;
fun_ = fun;
arg1_ = arg1;
}
virtual ~ObjClosure1() {
}
virtual void Run() {
(p_->*fun_)(arg1_);
}
private:
Obj* p_;
Funct fun_;
Arg1 arg1_;
};
public:
ObjClosure1(Obj* p, Funct fun, Arg1 arg1) {
p_ = p;
fun_ = fun;
arg1_ = arg1;
}
virtual ~ObjClosure1() {
}
virtual void Run() {
(p_->*fun_)(arg1_);
}
private:
Obj* p_;
Funct fun_;
Arg1 arg1_;
};
template <class Obj, class Funct, class Arg1, class Arg2>
template <class Obj, class Funct, class Arg1, class Arg2>
class ObjClosure2: public ClosureInterface {
public:
ObjClosure2(Obj* p, Funct fun, Arg1 arg1, Arg2 arg2) {
p_ = p;
fun_ = fun;
arg1_ = arg1;
arg2_ = arg2;
}
virtual ~ObjClosure2() {
}
virtual void Run() {
(p_->*fun_)(arg1_, arg2_);
}
private:
Obj* p_;
Funct fun_;
Arg1 arg1_;
Arg2 arg2_;
};
template <class Obj, class Funct, class Arg1, class Arg2, class Arg3>
public:
ObjClosure2(Obj* p, Funct fun, Arg1 arg1, Arg2 arg2) {
p_ = p;
fun_ = fun;
arg1_ = arg1;
arg2_ = arg2;
}
virtual ~ObjClosure2() {
}
virtual void Run() {
(p_->*fun_)(arg1_, arg2_);
}
private:
Obj* p_;
Funct fun_;
Arg1 arg1_;
Arg2 arg2_;
};
template <class Obj, class Funct, class Arg1, class Arg2, class Arg3>
class ObjClosure3: public ClosureInterface {
public:
ObjClosure3(Obj* p, Funct fun, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
p_ = p;
fun_ = fun;
arg1_ = arg1;
arg2_ = arg2;
arg3_ = arg3;
}
virtual ~ObjClosure3() {
}
virtual void Run() {
(p_->*fun_)(arg1_, arg2_, arg3_);
}
private:
Obj* p_;
Funct fun_;
Arg1 arg1_;
Arg2 arg2_;
Arg3 arg3_;
};
public:
ObjClosure3(Obj* p, Funct fun, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
p_ = p;
fun_ = fun;
arg1_ = arg1;
arg2_ = arg2;
arg3_ = arg3;
}
virtual ~ObjClosure3() {
}
virtual void Run() {
(p_->*fun_)(arg1_, arg2_, arg3_);
}
private:
Obj* p_;
Funct fun_;
Arg1 arg1_;
Arg2 arg2_;
Arg3 arg3_;
};
template<class R>
ClosureInterface* NewClosure(R (*fun)()) {
return new Closure0<R (*)()>(fun);
ClosureInterface* NewClosure(R(*fun)()) {
return new Closure0<R(*)()>(fun);
}
template<class R, class Arg1>
ClosureInterface* NewClosure(R (*fun)(Arg1), Arg1 arg1) {
return new Closure1<R (*)(Arg1), Arg1>(fun, arg1);
ClosureInterface* NewClosure(R(*fun)(Arg1), Arg1 arg1) {
return new Closure1<R(*)(Arg1), Arg1>(fun, arg1);
}
template<class R, class Arg1, class Arg2>
ClosureInterface* NewClosure(R (*fun)(Arg1, Arg2), Arg1 arg1, Arg2 arg2) {
return new Closure2<R (*)(Arg1, Arg2), Arg1, Arg2>(fun, arg1, arg2);
ClosureInterface* NewClosure(R(*fun)(Arg1, Arg2), Arg1 arg1, Arg2 arg2) {
return new Closure2<R(*)(Arg1, Arg2), Arg1, Arg2>(fun, arg1, arg2);
}
template<class R, class Arg1, class Arg2, class Arg3>
ClosureInterface* NewClosure(R (*fun)(Arg1, Arg2, Arg3), Arg1 arg1, Arg2 arg2, Arg3 arg3) {
return new Closure3<R (*)(Arg1, Arg2, Arg3), Arg1, Arg2, Arg3>(fun, arg1, arg2, arg3);
ClosureInterface* NewClosure(R(*fun)(Arg1, Arg2, Arg3), Arg1 arg1, Arg2 arg2, Arg3 arg3) {
return new Closure3<R(*)(Arg1, Arg2, Arg3), Arg1, Arg2, Arg3>(fun, arg1, arg2, arg3);
}
template<class R, class Obj>
ClosureInterface* NewClosure(Obj* obj, R (Obj::* fun)()) {
return new ObjClosure0<Obj, R (Obj::* )()>(obj, fun);
ClosureInterface* NewClosure(Obj* obj, R(Obj::* fun)()) {
return new ObjClosure0<Obj, R(Obj::*)()>(obj, fun);
}
template<class R, class Obj, class Arg1>
ClosureInterface* NewClosure(Obj* obj, R (Obj::* fun)(Arg1), Arg1 arg1) {
return new ObjClosure1<Obj, R (Obj::* )(Arg1), Arg1>(obj, fun, arg1);
ClosureInterface* NewClosure(Obj* obj, R(Obj::* fun)(Arg1), Arg1 arg1) {
return new ObjClosure1<Obj, R(Obj::*)(Arg1), Arg1>(obj, fun, arg1);
}
template<class R, class Obj, class Arg1, class Arg2>
ClosureInterface* NewClosure(Obj* obj, R (Obj::* fun)(Arg1, Arg2), Arg1 arg1, Arg2 arg2) {
return new ObjClosure2<Obj, R (Obj::*)(Arg1, Arg2), Arg1, Arg2>(obj, fun, arg1, arg2);
ClosureInterface* NewClosure(Obj* obj, R(Obj::* fun)(Arg1, Arg2), Arg1 arg1, Arg2 arg2) {
return new ObjClosure2<Obj, R(Obj::*)(Arg1, Arg2), Arg1, Arg2>(obj, fun, arg1, arg2);
}
template<class R, class Obj, class Arg1, class Arg2, class Arg3>
ClosureInterface* NewClosure(Obj* obj, R (Obj::* fun)(Arg1, Arg2, Arg3), Arg1 arg1, Arg2 arg2, Arg3 arg3) {
return new ObjClosure3<Obj, R (Obj::*)(Arg1, Arg2, Arg3), Arg1, Arg2, Arg3>(obj, fun, arg1, arg2, arg3);
ClosureInterface* NewClosure(Obj* obj, R(Obj::* fun)(Arg1, Arg2, Arg3), Arg1 arg1, Arg2 arg2, Arg3 arg3) {
return new ObjClosure3<Obj, R(Obj::*)(Arg1, Arg2, Arg3), Arg1, Arg2, Arg3>(obj, fun, arg1, arg2, arg3);
}
} // namespace limonp

View File

@ -27,21 +27,21 @@ namespace limonp {
using std::string;
enum Color {
BLACK = 30,
RED,
GREEN,
YELLOW,
BLUE,
PURPLE
BLACK = 30,
RED,
GREEN,
YELLOW,
BLUE,
PURPLE
}; // enum Color
static void ColorPrintln(enum Color color, const char * fmt, ...) {
va_list ap;
printf("\033[0;%dm", color);
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
printf("\033[0m\n"); // if not \n , in some situation , the next lines will be set the same color unexpectedly
va_list ap;
printf("\033[0;%dm", color);
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
printf("\033[0m\n"); // if not \n , in some situation , the next lines will be set the same color unexpectedly
}
} // namespace limonp

View File

@ -24,31 +24,31 @@
namespace limonp {
class Condition : NonCopyable {
public:
explicit Condition(MutexLock& mutex)
: mutex_(mutex) {
XCHECK(!pthread_cond_init(&pcond_, NULL));
}
public:
explicit Condition(MutexLock& mutex)
: mutex_(mutex) {
XCHECK(!pthread_cond_init(&pcond_, NULL));
}
~Condition() {
XCHECK(!pthread_cond_destroy(&pcond_));
}
~Condition() {
XCHECK(!pthread_cond_destroy(&pcond_));
}
void Wait() {
XCHECK(!pthread_cond_wait(&pcond_, mutex_.GetPthreadMutex()));
}
void Wait() {
XCHECK(!pthread_cond_wait(&pcond_, mutex_.GetPthreadMutex()));
}
void Notify() {
XCHECK(!pthread_cond_signal(&pcond_));
}
void Notify() {
XCHECK(!pthread_cond_signal(&pcond_));
}
void NotifyAll() {
XCHECK(!pthread_cond_broadcast(&pcond_));
}
void NotifyAll() {
XCHECK(!pthread_cond_broadcast(&pcond_));
}
private:
MutexLock& mutex_;
pthread_cond_t pcond_;
private:
MutexLock& mutex_;
pthread_cond_t pcond_;
}; // class Condition
} // namespace limonp

View File

@ -34,86 +34,86 @@ namespace limonp {
using namespace std;
class Config {
public:
explicit Config(const string& filePath) {
LoadFile(filePath);
}
operator bool () {
return !map_.empty();
}
string Get(const string& key, const string& defaultvalue) const {
map<string, string>::const_iterator it = map_.find(key);
if(map_.end() != it) {
return it->second;
public:
explicit Config(const string& filePath) {
LoadFile(filePath);
}
return defaultvalue;
}
int Get(const string& key, int defaultvalue) const {
string str = Get(key, "");
if("" == str) {
return defaultvalue;
}
return atoi(str.c_str());
}
const char* operator [] (const char* key) const {
if(NULL == key) {
return NULL;
}
map<string, string>::const_iterator it = map_.find(key);
if(map_.end() != it) {
return it->second.c_str();
}
return NULL;
}
string GetConfigInfo() const {
string res;
res << *this;
return res;
}
private:
void LoadFile(const string& filePath) {
ifstream ifs(filePath.c_str());
assert(ifs);
string line;
vector<string> vecBuf;
size_t lineno = 0;
while(getline(ifs, line)) {
lineno ++;
Trim(line);
if(line.empty() || StartsWith(line, "#")) {
continue;
}
vecBuf.clear();
Split(line, vecBuf, "=");
if(2 != vecBuf.size()) {
fprintf(stderr, "line[%s] illegal.\n", line.c_str());
assert(false);
continue;
}
string& key = vecBuf[0];
string& value = vecBuf[1];
Trim(key);
Trim(value);
if(!map_.insert(make_pair(key, value)).second) {
fprintf(stderr, "key[%s] already exits.\n", key.c_str());
assert(false);
continue;
}
operator bool () {
return !map_.empty();
}
ifs.close();
}
friend ostream& operator << (ostream& os, const Config& config);
string Get(const string& key, const string& defaultvalue) const {
map<string, string>::const_iterator it = map_.find(key);
if(map_.end() != it) {
return it->second;
}
return defaultvalue;
}
int Get(const string& key, int defaultvalue) const {
string str = Get(key, "");
if("" == str) {
return defaultvalue;
}
return atoi(str.c_str());
}
const char* operator [](const char* key) const {
if(NULL == key) {
return NULL;
}
map<string, string>::const_iterator it = map_.find(key);
if(map_.end() != it) {
return it->second.c_str();
}
return NULL;
}
map<string, string> map_;
string GetConfigInfo() const {
string res;
res << *this;
return res;
}
private:
void LoadFile(const string& filePath) {
ifstream ifs(filePath.c_str());
assert(ifs);
string line;
vector<string> vecBuf;
size_t lineno = 0;
while(getline(ifs, line)) {
lineno ++;
Trim(line);
if(line.empty() || StartsWith(line, "#")) {
continue;
}
vecBuf.clear();
Split(line, vecBuf, "=");
if(2 != vecBuf.size()) {
fprintf(stderr, "line[%s] illegal.\n", line.c_str());
assert(false);
continue;
}
string& key = vecBuf[0];
string& value = vecBuf[1];
Trim(key);
Trim(value);
if(!map_.insert(make_pair(key, value)).second) {
fprintf(stderr, "key[%s] already exits.\n", key.c_str());
assert(false);
continue;
}
}
ifs.close();
}
friend ostream& operator << (ostream& os, const Config& config);
map<string, string> map_;
}; // class Config
inline ostream& operator << (ostream& os, const Config& config) {
return os << config.map_;
return os << config.map_;
}
} // namespace limonp

View File

@ -33,58 +33,58 @@ namespace limonp {
using std::string;
class FileLock {
public:
FileLock() : fd_(-1), ok_(true) {
}
~FileLock() {
if(fd_ > 0) {
Close();
public:
FileLock() : fd_(-1), ok_(true) {
}
}
void Open(const string& fname) {
assert(fd_ == -1);
fd_ = open(fname.c_str(), O_RDWR | O_CREAT, 0644);
if(fd_ < 0) {
ok_ = false;
err_ = strerror(errno);
~FileLock() {
if(fd_ > 0) {
Close();
}
}
}
void Close() {
::close(fd_);
}
void Lock() {
if(LockOrUnlock(fd_, true) < 0) {
ok_ = false;
err_ = strerror(errno);
void Open(const string& fname) {
assert(fd_ == -1);
fd_ = open(fname.c_str(), O_RDWR | O_CREAT, 0644);
if(fd_ < 0) {
ok_ = false;
err_ = strerror(errno);
}
}
}
void UnLock() {
if(LockOrUnlock(fd_, false) < 0) {
ok_ = false;
err_ = strerror(errno);
void Close() {
::close(fd_);
}
void Lock() {
if(LockOrUnlock(fd_, true) < 0) {
ok_ = false;
err_ = strerror(errno);
}
}
void UnLock() {
if(LockOrUnlock(fd_, false) < 0) {
ok_ = false;
err_ = strerror(errno);
}
}
bool Ok() const {
return ok_;
}
string Error() const {
return err_;
}
private:
static int LockOrUnlock(int fd, bool lock) {
errno = 0;
struct flock f;
memset(&f, 0, sizeof(f));
f.l_type = (lock ? F_WRLCK : F_UNLCK);
f.l_whence = SEEK_SET;
f.l_start = 0;
f.l_len = 0; // Lock/unlock entire file
return fcntl(fd, F_SETLK, &f);
}
}
bool Ok() const {
return ok_;
}
string Error() const {
return err_;
}
private:
static int LockOrUnlock(int fd, bool lock) {
errno = 0;
struct flock f;
memset(&f, 0, sizeof(f));
f.l_type = (lock ? F_WRLCK : F_UNLCK);
f.l_whence = SEEK_SET;
f.l_start = 0;
f.l_len = 0; // Lock/unlock entire file
return fcntl(fd, F_SETLK, &f);
}
int fd_;
bool ok_;
string err_;
int fd_;
bool ok_;
string err_;
}; // class FileLock
}// namespace limonp

View File

@ -33,123 +33,123 @@ using namespace std;
const size_t LOCAL_VECTOR_BUFFER_SIZE = 16;
template <class T>
class LocalVector {
public:
typedef const T* const_iterator ;
typedef T value_type;
typedef size_t size_type;
private:
T buffer_[LOCAL_VECTOR_BUFFER_SIZE];
T * ptr_;
size_t size_;
size_t capacity_;
public:
LocalVector() {
init_();
};
LocalVector(const LocalVector<T>& vec) {
init_();
*this = vec;
}
LocalVector(const_iterator begin, const_iterator end) { // TODO: make it faster
init_();
while(begin != end) {
push_back(*begin++);
public:
typedef const T* const_iterator ;
typedef T value_type;
typedef size_t size_type;
private:
T buffer_[LOCAL_VECTOR_BUFFER_SIZE];
T * ptr_;
size_t size_;
size_t capacity_;
public:
LocalVector() {
init_();
};
LocalVector(const LocalVector<T>& vec) {
init_();
*this = vec;
}
}
LocalVector(size_t size, const T& t) { // TODO: make it faster
init_();
while(size--) {
push_back(t);
LocalVector(const_iterator begin, const_iterator end) { // TODO: make it faster
init_();
while(begin != end) {
push_back(*begin++);
}
}
}
~LocalVector() {
if(ptr_ != buffer_) {
free(ptr_);
LocalVector(size_t size, const T& t) { // TODO: make it faster
init_();
while(size--) {
push_back(t);
}
}
};
public:
LocalVector<T>& operator = (const LocalVector<T>& vec) {
clear();
size_ = vec.size();
capacity_ = vec.capacity();
if(vec.buffer_ == vec.ptr_) {
memcpy(buffer_, vec.buffer_, sizeof(T) * size_);
ptr_ = buffer_;
} else {
ptr_ = (T*) malloc(vec.capacity() * sizeof(T));
assert(ptr_);
memcpy(ptr_, vec.ptr_, vec.size() * sizeof(T));
~LocalVector() {
if(ptr_ != buffer_) {
free(ptr_);
}
};
public:
LocalVector<T>& operator = (const LocalVector<T>& vec) {
clear();
size_ = vec.size();
capacity_ = vec.capacity();
if(vec.buffer_ == vec.ptr_) {
memcpy(buffer_, vec.buffer_, sizeof(T) * size_);
ptr_ = buffer_;
} else {
ptr_ = (T*) malloc(vec.capacity() * sizeof(T));
assert(ptr_);
memcpy(ptr_, vec.ptr_, vec.size() * sizeof(T));
}
return *this;
}
return *this;
}
private:
void init_() {
ptr_ = buffer_;
size_ = 0;
capacity_ = LOCAL_VECTOR_BUFFER_SIZE;
}
public:
T& operator [] (size_t i) {
return ptr_[i];
}
const T& operator [] (size_t i) const {
return ptr_[i];
}
void push_back(const T& t) {
if(size_ == capacity_) {
assert(capacity_);
reserve(capacity_ * 2);
private:
void init_() {
ptr_ = buffer_;
size_ = 0;
capacity_ = LOCAL_VECTOR_BUFFER_SIZE;
}
ptr_[size_ ++ ] = t;
}
void reserve(size_t size) {
if(size <= capacity_) {
return;
public:
T& operator [](size_t i) {
return ptr_[i];
}
T * next = (T*)malloc(sizeof(T) * size);
assert(next);
T * old = ptr_;
ptr_ = next;
memcpy(ptr_, old, sizeof(T) * capacity_);
capacity_ = size;
if(old != buffer_) {
free(old);
const T& operator [](size_t i) const {
return ptr_[i];
}
}
bool empty() const {
return 0 == size();
}
size_t size() const {
return size_;
}
size_t capacity() const {
return capacity_;
}
const_iterator begin() const {
return ptr_;
}
const_iterator end() const {
return ptr_ + size_;
}
void clear() {
if(ptr_ != buffer_) {
free(ptr_);
void push_back(const T& t) {
if(size_ == capacity_) {
assert(capacity_);
reserve(capacity_ * 2);
}
ptr_[size_ ++ ] = t;
}
void reserve(size_t size) {
if(size <= capacity_) {
return;
}
T * next = (T*)malloc(sizeof(T) * size);
assert(next);
T * old = ptr_;
ptr_ = next;
memcpy(ptr_, old, sizeof(T) * capacity_);
capacity_ = size;
if(old != buffer_) {
free(old);
}
}
bool empty() const {
return 0 == size();
}
size_t size() const {
return size_;
}
size_t capacity() const {
return capacity_;
}
const_iterator begin() const {
return ptr_;
}
const_iterator end() const {
return ptr_ + size_;
}
void clear() {
if(ptr_ != buffer_) {
free(ptr_);
}
init_();
}
init_();
}
};
template <class T>
ostream & operator << (ostream& os, const LocalVector<T>& vec) {
if(vec.empty()) {
return os << "[]";
}
os<<"[\""<<vec[0];
for(size_t i = 1; i < vec.size(); i++) {
os<<"\", \""<<vec[i];
}
os<<"\"]";
return os;
if(vec.empty()) {
return os << "[]";
}
os << "[\"" << vec[0];
for(size_t i = 1; i < vec.size(); i++) {
os << "\", \"" << vec[i];
}
os << "\"]";
return os;
}
}

View File

@ -32,61 +32,61 @@
#error "XCHECK has been defined already"
#endif // XCHECK
#define XLOG(level) limonp::Logger(limonp::LL_##level, __FILE__, __LINE__).Stream()
#define XLOG(level) limonp::Logger(limonp::LL_##level, __FILE__, __LINE__).Stream()
#define XCHECK(exp) if(!(exp)) XLOG(FATAL) << "exp: ["#exp << "] false. "
namespace limonp {
enum {
LL_DEBUG = 0,
LL_INFO = 1,
LL_WARNING = 2,
LL_ERROR = 3,
LL_FATAL = 4,
LL_DEBUG = 0,
LL_INFO = 1,
LL_WARNING = 2,
LL_ERROR = 3,
LL_FATAL = 4,
}; // enum
static const char * LOG_LEVEL_ARRAY[] = {"DEBUG","INFO","WARN","ERROR","FATAL"};
static const char * LOG_LEVEL_ARRAY[] = {"DEBUG", "INFO", "WARN", "ERROR", "FATAL"};
static const char * LOG_TIME_FORMAT = "%Y-%m-%d %H:%M:%S";
class Logger {
public:
Logger(size_t level, const char* filename, int lineno)
: level_(level) {
public:
Logger(size_t level, const char* filename, int lineno)
: level_(level) {
#ifdef LOGGING_LEVEL
if (level_ < LOGGING_LEVEL) {
return;
}
if(level_ < LOGGING_LEVEL) {
return;
}
#endif
assert(level_ <= sizeof(LOG_LEVEL_ARRAY)/sizeof(*LOG_LEVEL_ARRAY));
char buf[32];
time_t now;
time(&now);
strftime(buf, sizeof(buf), LOG_TIME_FORMAT, localtime(&now));
stream_ << buf
<< " " << filename
<< ":" << lineno
<< " " << LOG_LEVEL_ARRAY[level_]
<< " ";
}
~Logger() {
#ifdef LOGGING_LEVEL
if (level_ < LOGGING_LEVEL) {
return;
}
#endif
std::cerr << stream_.str() << std::endl;
if (level_ == LL_FATAL) {
abort();
assert(level_ <= sizeof(LOG_LEVEL_ARRAY) / sizeof(*LOG_LEVEL_ARRAY));
char buf[32];
time_t now;
time(&now);
strftime(buf, sizeof(buf), LOG_TIME_FORMAT, localtime(&now));
stream_ << buf
<< " " << filename
<< ":" << lineno
<< " " << LOG_LEVEL_ARRAY[level_]
<< " ";
}
~Logger() {
#ifdef LOGGING_LEVEL
if(level_ < LOGGING_LEVEL) {
return;
}
#endif
std::cerr << stream_.str() << std::endl;
if(level_ == LL_FATAL) {
abort();
}
}
}
std::ostream& Stream() {
return stream_;
}
std::ostream& Stream() {
return stream_;
}
private:
std::ostringstream stream_;
size_t level_;
private:
std::ostringstream stream_;
size_t level_;
}; // class Logger
} // namespace limonp

View File

@ -103,313 +103,313 @@ typedef unsigned short int UINT2;
typedef unsigned int UINT4;
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
// convenient object that wraps
// the C-functions for use in C++ only
class MD5 {
private:
struct __context_t {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} context ;
private:
struct __context_t {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} context ;
//#pragma region static helper functions
// The core of the MD5 algorithm is here.
// MD5 basic transformation. Transforms state based on block.
static void MD5Transform( UINT4 state[4], unsigned char block[64] ) {
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
//#pragma region static helper functions
// The core of the MD5 algorithm is here.
// MD5 basic transformation. Transforms state based on block.
static void MD5Transform(UINT4 state[4], unsigned char block[64]) {
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
Decode(x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 1 */
FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 2 */
GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 3 */
HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
/* Round 4 */
II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
// Zeroize sensitive information.
memset((POINTER)x, 0, sizeof (x));
}
// Encodes input (UINT4) into output (unsigned char). Assumes len is
// a multiple of 4.
static void Encode( unsigned char *output, UINT4 *input, unsigned int len ) {
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
// Zeroize sensitive information.
memset((POINTER)x, 0, sizeof(x));
}
}
// Decodes input (unsigned char) into output (UINT4). Assumes len is
// a multiple of 4.
static void Decode( UINT4 *output, unsigned char *input, unsigned int len ) {
unsigned int i, j;
// Encodes input (UINT4) into output (unsigned char). Assumes len is
// a multiple of 4.
static void Encode(unsigned char *output, UINT4 *input, unsigned int len) {
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
//#pragma endregion
public:
// MAIN FUNCTIONS
MD5() {
Init() ;
}
// MD5 initialization. Begins an MD5 operation, writing a new context.
void Init() {
context.count[0] = context.count[1] = 0;
// Load magic initialization constants.
context.state[0] = 0x67452301;
context.state[1] = 0xefcdab89;
context.state[2] = 0x98badcfe;
context.state[3] = 0x10325476;
}
// MD5 block update operation. Continues an MD5 message-digest
// operation, processing another message block, and updating the
// context.
void Update(
unsigned char *input, // input block
unsigned int inputLen ) { // length of input block
unsigned int i, index, partLen;
// Compute number of bytes mod 64
index = (unsigned int)((context.count[0] >> 3) & 0x3F);
// Update number of bits
if ((context.count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
context.count[1]++;
context.count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
// Transform as many times as possible.
if (inputLen >= partLen) {
memcpy((POINTER)&context.buffer[index], (POINTER)input, partLen);
MD5Transform (context.state, context.buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (context.state, &input[i]);
index = 0;
} else
i = 0;
/* Buffer remaining input */
memcpy((POINTER)&context.buffer[index], (POINTER)&input[i], inputLen-i);
}
// MD5 finalization. Ends an MD5 message-digest operation, writing the
// the message digest and zeroizing the context.
// Writes to digestRaw
void Final() {
unsigned char bits[8];
unsigned int index, padLen;
// Save number of bits
Encode( bits, context.count, 8 );
// Pad out to 56 mod 64.
index = (unsigned int)((context.count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
Update( PADDING, padLen );
// Append length (before padding)
Update( bits, 8 );
// Store state in digest
Encode( digestRaw, context.state, 16);
// Zeroize sensitive information.
memset((POINTER)&context, 0, sizeof (context));
writeToString() ;
}
/// Buffer must be 32+1 (nul) = 33 chars long at least
void writeToString() {
int pos ;
for( pos = 0 ; pos < 16 ; pos++ )
sprintf( digestChars+(pos*2), "%02x", digestRaw[pos] ) ;
}
public:
// an MD5 digest is a 16-byte number (32 hex digits)
BYTE digestRaw[ 16 ] ;
// This version of the digest is actually
// a "printf'd" version of the digest.
char digestChars[ 33 ] ;
/// Load a file from disk and digest it
// Digests a file and returns the result.
const char* digestFile( const char *filename ) {
if (NULL == filename || strcmp(filename, "") == 0)
return NULL;
Init() ;
FILE *file;
unsigned char buffer[1024] ;
if((file = fopen (filename, "rb")) == NULL) {
return NULL;
for(i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j + 1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j + 2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j + 3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
int len;
while( (len = fread( buffer, 1, 1024, file )) )
Update( buffer, len ) ;
Final();
fclose( file );
// Decodes input (unsigned char) into output (UINT4). Assumes len is
// a multiple of 4.
static void Decode(UINT4 *output, unsigned char *input, unsigned int len) {
unsigned int i, j;
return digestChars ;
}
for(i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j + 1]) << 8) |
(((UINT4)input[j + 2]) << 16) | (((UINT4)input[j + 3]) << 24);
}
//#pragma endregion
/// Digests a byte-array already in memory
const char* digestMemory( BYTE *memchunk, int len ) {
if (NULL == memchunk)
return NULL;
Init() ;
Update( memchunk, len ) ;
Final() ;
public:
// MAIN FUNCTIONS
MD5() {
Init() ;
}
return digestChars ;
}
// MD5 initialization. Begins an MD5 operation, writing a new context.
void Init() {
context.count[0] = context.count[1] = 0;
// Digests a string and prints the result.
const char* digestString(const char *string ) {
if (string == NULL)
return NULL;
// Load magic initialization constants.
context.state[0] = 0x67452301;
context.state[1] = 0xefcdab89;
context.state[2] = 0x98badcfe;
context.state[3] = 0x10325476;
}
Init() ;
Update( (unsigned char*)string, strlen(string) ) ;
Final() ;
// MD5 block update operation. Continues an MD5 message-digest
// operation, processing another message block, and updating the
// context.
void Update(
unsigned char *input, // input block
unsigned int inputLen) { // length of input block
unsigned int i, index, partLen;
return digestChars ;
}
// Compute number of bytes mod 64
index = (unsigned int)((context.count[0] >> 3) & 0x3F);
// Update number of bits
if((context.count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
context.count[1]++;
context.count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
// Transform as many times as possible.
if(inputLen >= partLen) {
memcpy((POINTER)&context.buffer[index], (POINTER)input, partLen);
MD5Transform(context.state, context.buffer);
for(i = partLen; i + 63 < inputLen; i += 64)
MD5Transform(context.state, &input[i]);
index = 0;
} else
i = 0;
/* Buffer remaining input */
memcpy((POINTER)&context.buffer[index], (POINTER)&input[i], inputLen - i);
}
// MD5 finalization. Ends an MD5 message-digest operation, writing the
// the message digest and zeroizing the context.
// Writes to digestRaw
void Final() {
unsigned char bits[8];
unsigned int index, padLen;
// Save number of bits
Encode(bits, context.count, 8);
// Pad out to 56 mod 64.
index = (unsigned int)((context.count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
Update(PADDING, padLen);
// Append length (before padding)
Update(bits, 8);
// Store state in digest
Encode(digestRaw, context.state, 16);
// Zeroize sensitive information.
memset((POINTER)&context, 0, sizeof(context));
writeToString() ;
}
/// Buffer must be 32+1 (nul) = 33 chars long at least
void writeToString() {
int pos ;
for(pos = 0 ; pos < 16 ; pos++)
sprintf(digestChars + (pos * 2), "%02x", digestRaw[pos]) ;
}
public:
// an MD5 digest is a 16-byte number (32 hex digits)
BYTE digestRaw[ 16 ] ;
// This version of the digest is actually
// a "printf'd" version of the digest.
char digestChars[ 33 ] ;
/// Load a file from disk and digest it
// Digests a file and returns the result.
const char* digestFile(const char *filename) {
if(NULL == filename || strcmp(filename, "") == 0)
return NULL;
Init() ;
FILE *file;
unsigned char buffer[1024] ;
if((file = fopen(filename, "rb")) == NULL) {
return NULL;
}
int len;
while((len = fread(buffer, 1, 1024, file)))
Update(buffer, len) ;
Final();
fclose(file);
return digestChars ;
}
/// Digests a byte-array already in memory
const char* digestMemory(BYTE *memchunk, int len) {
if(NULL == memchunk)
return NULL;
Init() ;
Update(memchunk, len) ;
Final() ;
return digestChars ;
}
// Digests a string and prints the result.
const char* digestString(const char *string) {
if(string == NULL)
return NULL;
Init() ;
Update((unsigned char*)string, strlen(string)) ;
Final() ;
return digestChars ;
}
};
inline bool md5String(const char* str, std::string& res) {
if (NULL == str) {
res = "";
return false;
}
if(NULL == str) {
res = "";
return false;
}
MD5 md5;
const char *pRes = md5.digestString(str);
if (NULL == pRes) {
res = "";
return false;
}
MD5 md5;
const char *pRes = md5.digestString(str);
if(NULL == pRes) {
res = "";
return false;
}
res = pRes;
return true;
res = pRes;
return true;
}
inline bool md5File(const char* filepath, std::string& res) {
if (NULL == filepath || strcmp(filepath, "") == 0) {
res = "";
return false;
}
if(NULL == filepath || strcmp(filepath, "") == 0) {
res = "";
return false;
}
MD5 md5;
const char *pRes = md5.digestFile(filepath);
MD5 md5;
const char *pRes = md5.digestFile(filepath);
if (NULL == pRes) {
res = "";
return false;
}
if(NULL == pRes) {
res = "";
return false;
}
res = pRes;
return true;
res = pRes;
return true;
}
}
#endif

View File

@ -26,40 +26,40 @@
namespace limonp {
class MutexLock: NonCopyable {
public:
MutexLock() {
XCHECK(!pthread_mutex_init(&mutex_, NULL));
}
~MutexLock() {
XCHECK(!pthread_mutex_destroy(&mutex_));
}
pthread_mutex_t* GetPthreadMutex() {
return &mutex_;
}
public:
MutexLock() {
XCHECK(!pthread_mutex_init(&mutex_, NULL));
}
~MutexLock() {
XCHECK(!pthread_mutex_destroy(&mutex_));
}
pthread_mutex_t* GetPthreadMutex() {
return &mutex_;
}
private:
void Lock() {
XCHECK(!pthread_mutex_lock(&mutex_));
}
void Unlock() {
XCHECK(!pthread_mutex_unlock(&mutex_));
}
friend class MutexLockGuard;
private:
void Lock() {
XCHECK(!pthread_mutex_lock(&mutex_));
}
void Unlock() {
XCHECK(!pthread_mutex_unlock(&mutex_));
}
friend class MutexLockGuard;
pthread_mutex_t mutex_;
pthread_mutex_t mutex_;
}; // class MutexLock
class MutexLockGuard: NonCopyable {
public:
explicit MutexLockGuard(MutexLock & mutex)
: mutex_(mutex) {
mutex_.Lock();
}
~MutexLockGuard() {
mutex_.Unlock();
}
private:
MutexLock & mutex_;
public:
explicit MutexLockGuard(MutexLock & mutex)
: mutex_(mutex) {
mutex_.Lock();
}
~MutexLockGuard() {
mutex_.Unlock();
}
private:
MutexLock & mutex_;
}; // class MutexLockGuard
#define MutexLockGuard(x) XCHECK(false);

View File

@ -22,14 +22,14 @@
namespace limonp {
class NonCopyable {
protected:
NonCopyable() {
}
~NonCopyable() {
}
private:
NonCopyable(const NonCopyable& );
const NonCopyable& operator=(const NonCopyable& );
protected:
NonCopyable() {
}
~NonCopyable() {
}
private:
NonCopyable(const NonCopyable&);
const NonCopyable& operator=(const NonCopyable&);
}; // class NonCopyable
} // namespace limonp

View File

@ -51,123 +51,123 @@ namespace std {
template<typename T>
ostream& operator << (ostream& os, const vector<T>& v) {
if(v.empty()) {
return os << "[]";
}
os<<"["<<v[0];
for(size_t i = 1; i < v.size(); i++) {
os<<", "<<v[i];
}
os<<"]";
return os;
if(v.empty()) {
return os << "[]";
}
os << "[" << v[0];
for(size_t i = 1; i < v.size(); i++) {
os << ", " << v[i];
}
os << "]";
return os;
}
template<>
inline ostream& operator << (ostream& os, const vector<string>& v) {
if(v.empty()) {
return os << "[]";
}
os<<"[\""<<v[0];
for(size_t i = 1; i < v.size(); i++) {
os<<"\", \""<<v[i];
}
os<<"\"]";
return os;
if(v.empty()) {
return os << "[]";
}
os << "[\"" << v[0];
for(size_t i = 1; i < v.size(); i++) {
os << "\", \"" << v[i];
}
os << "\"]";
return os;
}
template<typename T>
ostream& operator << (ostream& os, const deque<T>& dq) {
if(dq.empty()) {
return os << "[]";
}
os<<"[\""<<dq[0];
for(size_t i = 1; i < dq.size(); i++) {
os<<"\", \""<<dq[i];
}
os<<"\"]";
return os;
if(dq.empty()) {
return os << "[]";
}
os << "[\"" << dq[0];
for(size_t i = 1; i < dq.size(); i++) {
os << "\", \"" << dq[i];
}
os << "\"]";
return os;
}
template<class T1, class T2>
ostream& operator << (ostream& os, const pair<T1, T2>& pr) {
os << pr.first << ":" << pr.second ;
return os;
os << pr.first << ":" << pr.second ;
return os;
}
template<class T>
string& operator << (string& str, const T& obj) {
stringstream ss;
ss << obj; // call ostream& operator << (ostream& os,
return str = ss.str();
stringstream ss;
ss << obj; // call ostream& operator << (ostream& os,
return str = ss.str();
}
template<class T1, class T2>
ostream& operator << (ostream& os, const map<T1, T2>& mp) {
if(mp.empty()) {
os<<"{}";
return os;
}
os<<'{';
typename map<T1, T2>::const_iterator it = mp.begin();
os<<*it;
it++;
while(it != mp.end()) {
os<<", "<<*it;
if(mp.empty()) {
os << "{}";
return os;
}
os << '{';
typename map<T1, T2>::const_iterator it = mp.begin();
os << *it;
it++;
}
os<<'}';
return os;
while(it != mp.end()) {
os << ", " << *it;
it++;
}
os << '}';
return os;
}
template<class T1, class T2>
ostream& operator << (ostream& os, const std::unordered_map<T1, T2>& mp) {
if(mp.empty()) {
return os << "{}";
}
os<<'{';
typename std::unordered_map<T1, T2>::const_iterator it = mp.begin();
os<<*it;
it++;
while(it != mp.end()) {
os<<", "<<*it++;
}
return os<<'}';
if(mp.empty()) {
return os << "{}";
}
os << '{';
typename std::unordered_map<T1, T2>::const_iterator it = mp.begin();
os << *it;
it++;
while(it != mp.end()) {
os << ", " << *it++;
}
return os << '}';
}
template<class T>
ostream& operator << (ostream& os, const set<T>& st) {
if(st.empty()) {
os << "{}";
return os;
}
os<<'{';
typename set<T>::const_iterator it = st.begin();
os<<*it;
it++;
while(it != st.end()) {
os<<", "<<*it;
if(st.empty()) {
os << "{}";
return os;
}
os << '{';
typename set<T>::const_iterator it = st.begin();
os << *it;
it++;
}
os<<'}';
return os;
while(it != st.end()) {
os << ", " << *it;
it++;
}
os << '}';
return os;
}
template<class KeyType, class ContainType>
bool IsIn(const ContainType& contain, const KeyType& key) {
return contain.end() != contain.find(key);
return contain.end() != contain.find(key);
}
template<class T>
basic_string<T> & operator << (basic_string<T> & s, ifstream & ifs) {
return s.assign((istreambuf_iterator<T>(ifs)), istreambuf_iterator<T>());
return s.assign((istreambuf_iterator<T>(ifs)), istreambuf_iterator<T>());
}
template<class T>
ofstream & operator << (ofstream & ofs, const basic_string<T>& s) {
ostreambuf_iterator<T> itr (ofs);
copy(s.begin(), s.end(), itr);
return ofs;
ostreambuf_iterator<T> itr(ofs);
copy(s.begin(), s.end(), itr);
return ofs;
}
} // namespace std

View File

@ -44,339 +44,339 @@
namespace limonp {
using namespace std;
inline string StringFormat(const char* fmt, ...) {
int size = 256;
std::string str;
va_list ap;
while (1) {
str.resize(size);
va_start(ap, fmt);
int n = vsnprintf((char *)str.c_str(), size, fmt, ap);
va_end(ap);
if (n > -1 && n < size) {
str.resize(n);
return str;
int size = 256;
std::string str;
va_list ap;
while(1) {
str.resize(size);
va_start(ap, fmt);
int n = vsnprintf((char *)str.c_str(), size, fmt, ap);
va_end(ap);
if(n > -1 && n < size) {
str.resize(n);
return str;
}
if(n > -1)
size = n + 1;
else
size *= 2;
}
if (n > -1)
size = n + 1;
else
size *= 2;
}
return str;
return str;
}
template<class T>
void Join(T begin, T end, string& res, const string& connector) {
if(begin == end) {
return;
}
stringstream ss;
ss<<*begin;
begin++;
while(begin != end) {
ss << connector << *begin;
begin ++;
}
res = ss.str();
if(begin == end) {
return;
}
stringstream ss;
ss << *begin;
begin++;
while(begin != end) {
ss << connector << *begin;
begin ++;
}
res = ss.str();
}
template<class T>
string Join(T begin, T end, const string& connector) {
string res;
Join(begin ,end, res, connector);
return res;
string res;
Join(begin, end, res, connector);
return res;
}
inline string& Upper(string& str) {
transform(str.begin(), str.end(), str.begin(), (int (*)(int))toupper);
return str;
transform(str.begin(), str.end(), str.begin(), (int (*)(int))toupper);
return str;
}
inline string& Lower(string& str) {
transform(str.begin(), str.end(), str.begin(), (int (*)(int))tolower);
return str;
transform(str.begin(), str.end(), str.begin(), (int (*)(int))tolower);
return str;
}
inline bool IsSpace(unsigned c) {
// when passing large int as the argument of isspace, it core dump, so here need a type cast.
return c > 0xff ? false : std::isspace(c & 0xff) != 0;
// when passing large int as the argument of isspace, it core dump, so here need a type cast.
return c > 0xff ? false : std::isspace(c & 0xff) != 0;
}
inline std::string& LTrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<unsigned, bool>(IsSpace))));
return s;
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<unsigned, bool>(IsSpace))));
return s;
}
inline std::string& RTrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<unsigned, bool>(IsSpace))).base(), s.end());
return s;
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<unsigned, bool>(IsSpace))).base(), s.end());
return s;
}
inline std::string& Trim(std::string &s) {
return LTrim(RTrim(s));
return LTrim(RTrim(s));
}
inline std::string& LTrim(std::string & s, char x) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::bind2nd(std::equal_to<char>(), x))));
return s;
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::bind2nd(std::equal_to<char>(), x))));
return s;
}
inline std::string& RTrim(std::string & s, char x) {
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::bind2nd(std::equal_to<char>(), x))).base(), s.end());
return s;
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::bind2nd(std::equal_to<char>(), x))).base(), s.end());
return s;
}
inline std::string& Trim(std::string &s, char x) {
return LTrim(RTrim(s, x), x);
return LTrim(RTrim(s, x), x);
}
inline void Split(const string& src, vector<string>& res, const string& pattern, size_t maxsplit = string::npos) {
res.clear();
size_t Start = 0;
size_t end = 0;
string sub;
while(Start < src.size()) {
end = src.find_first_of(pattern, Start);
if(string::npos == end || res.size() >= maxsplit) {
sub = src.substr(Start);
res.push_back(sub);
return;
res.clear();
size_t Start = 0;
size_t end = 0;
string sub;
while(Start < src.size()) {
end = src.find_first_of(pattern, Start);
if(string::npos == end || res.size() >= maxsplit) {
sub = src.substr(Start);
res.push_back(sub);
return;
}
sub = src.substr(Start, end - Start);
res.push_back(sub);
Start = end + 1;
}
sub = src.substr(Start, end - Start);
res.push_back(sub);
Start = end + 1;
}
return;
return;
}
inline vector<string> Split(const string& src, const string& pattern, size_t maxsplit = string::npos) {
vector<string> res;
Split(src, res, pattern, maxsplit);
return res;
vector<string> res;
Split(src, res, pattern, maxsplit);
return res;
}
inline bool StartsWith(const string& str, const string& prefix) {
if(prefix.length() > str.length()) {
return false;
}
return 0 == str.compare(0, prefix.length(), prefix);
if(prefix.length() > str.length()) {
return false;
}
return 0 == str.compare(0, prefix.length(), prefix);
}
inline bool EndsWith(const string& str, const string& suffix) {
if(suffix.length() > str.length()) {
return false;
}
return 0 == str.compare(str.length() - suffix.length(), suffix.length(), suffix);
if(suffix.length() > str.length()) {
return false;
}
return 0 == str.compare(str.length() - suffix.length(), suffix.length(), suffix);
}
inline bool IsInStr(const string& str, char ch) {
return str.find(ch) != string::npos;
return str.find(ch) != string::npos;
}
inline uint16_t TwocharToUint16(char high, char low) {
return (((uint16_t(high) & 0x00ff ) << 8) | (uint16_t(low) & 0x00ff));
return (((uint16_t(high) & 0x00ff) << 8) | (uint16_t(low) & 0x00ff));
}
template <class Uint16Container>
bool Utf8ToUnicode(const char * const str, size_t len, Uint16Container& vec) {
if(!str) {
return false;
}
char ch1, ch2;
uint16_t tmp;
vec.clear();
for(size_t i = 0; i < len;) {
if(!(str[i] & 0x80)) { // 0xxxxxxx
vec.push_back(str[i]);
i++;
} else if ((uint8_t)str[i] <= 0xdf && i + 1 < len) { // 110xxxxxx
ch1 = (str[i] >> 2) & 0x07;
ch2 = (str[i+1] & 0x3f) | ((str[i] & 0x03) << 6 );
tmp = (((uint16_t(ch1) & 0x00ff ) << 8) | (uint16_t(ch2) & 0x00ff));
vec.push_back(tmp);
i += 2;
} else if((uint8_t)str[i] <= 0xef && i + 2 < len) {
ch1 = ((uint8_t)str[i] << 4) | ((str[i+1] >> 2) & 0x0f );
ch2 = (((uint8_t)str[i+1]<<6) & 0xc0) | (str[i+2] & 0x3f);
tmp = (((uint16_t(ch1) & 0x00ff ) << 8) | (uint16_t(ch2) & 0x00ff));
vec.push_back(tmp);
i += 3;
} else {
return false;
if(!str) {
return false;
}
}
return true;
char ch1, ch2;
uint16_t tmp;
vec.clear();
for(size_t i = 0; i < len;) {
if(!(str[i] & 0x80)) { // 0xxxxxxx
vec.push_back(str[i]);
i++;
} else if((uint8_t)str[i] <= 0xdf && i + 1 < len) { // 110xxxxxx
ch1 = (str[i] >> 2) & 0x07;
ch2 = (str[i + 1] & 0x3f) | ((str[i] & 0x03) << 6);
tmp = (((uint16_t(ch1) & 0x00ff) << 8) | (uint16_t(ch2) & 0x00ff));
vec.push_back(tmp);
i += 2;
} else if((uint8_t)str[i] <= 0xef && i + 2 < len) {
ch1 = ((uint8_t)str[i] << 4) | ((str[i + 1] >> 2) & 0x0f);
ch2 = (((uint8_t)str[i + 1] << 6) & 0xc0) | (str[i + 2] & 0x3f);
tmp = (((uint16_t(ch1) & 0x00ff) << 8) | (uint16_t(ch2) & 0x00ff));
vec.push_back(tmp);
i += 3;
} else {
return false;
}
}
return true;
}
template <class Uint16Container>
bool Utf8ToUnicode(const string& str, Uint16Container& vec) {
return Utf8ToUnicode(str.c_str(), str.size(), vec);
return Utf8ToUnicode(str.c_str(), str.size(), vec);
}
template <class Uint32Container>
bool Utf8ToUnicode32(const string& str, Uint32Container& vec) {
uint32_t tmp;
vec.clear();
for(size_t i = 0; i < str.size();) {
if(!(str[i] & 0x80)) { // 0xxxxxxx
// 7bit, total 7bit
tmp = (uint8_t)(str[i]) & 0x7f;
i++;
} else if ((uint8_t)str[i] <= 0xdf && i + 1 < str.size()) { // 110xxxxxx
// 5bit, total 5bit
tmp = (uint8_t)(str[i]) & 0x1f;
uint32_t tmp;
vec.clear();
for(size_t i = 0; i < str.size();) {
if(!(str[i] & 0x80)) { // 0xxxxxxx
// 7bit, total 7bit
tmp = (uint8_t)(str[i]) & 0x7f;
i++;
} else if((uint8_t)str[i] <= 0xdf && i + 1 < str.size()) { // 110xxxxxx
// 5bit, total 5bit
tmp = (uint8_t)(str[i]) & 0x1f;
// 6bit, total 11bit
tmp <<= 6;
tmp |= (uint8_t)(str[i+1]) & 0x3f;
i += 2;
} else if((uint8_t)str[i] <= 0xef && i + 2 < str.size()) { // 1110xxxxxx
// 4bit, total 4bit
tmp = (uint8_t)(str[i]) & 0x0f;
// 6bit, total 11bit
tmp <<= 6;
tmp |= (uint8_t)(str[i + 1]) & 0x3f;
i += 2;
} else if((uint8_t)str[i] <= 0xef && i + 2 < str.size()) { // 1110xxxxxx
// 4bit, total 4bit
tmp = (uint8_t)(str[i]) & 0x0f;
// 6bit, total 10bit
tmp <<= 6;
tmp |= (uint8_t)(str[i+1]) & 0x3f;
// 6bit, total 10bit
tmp <<= 6;
tmp |= (uint8_t)(str[i + 1]) & 0x3f;
// 6bit, total 16bit
tmp <<= 6;
tmp |= (uint8_t)(str[i+2]) & 0x3f;
// 6bit, total 16bit
tmp <<= 6;
tmp |= (uint8_t)(str[i + 2]) & 0x3f;
i += 3;
} else if((uint8_t)str[i] <= 0xf7 && i + 3 < str.size()) { // 11110xxxx
// 3bit, total 3bit
tmp = (uint8_t)(str[i]) & 0x07;
i += 3;
} else if((uint8_t)str[i] <= 0xf7 && i + 3 < str.size()) { // 11110xxxx
// 3bit, total 3bit
tmp = (uint8_t)(str[i]) & 0x07;
// 6bit, total 9bit
tmp <<= 6;
tmp |= (uint8_t)(str[i+1]) & 0x3f;
// 6bit, total 9bit
tmp <<= 6;
tmp |= (uint8_t)(str[i + 1]) & 0x3f;
// 6bit, total 15bit
tmp <<= 6;
tmp |= (uint8_t)(str[i+2]) & 0x3f;
// 6bit, total 15bit
tmp <<= 6;
tmp |= (uint8_t)(str[i + 2]) & 0x3f;
// 6bit, total 21bit
tmp <<= 6;
tmp |= (uint8_t)(str[i+3]) & 0x3f;
// 6bit, total 21bit
tmp <<= 6;
tmp |= (uint8_t)(str[i + 3]) & 0x3f;
i += 4;
} else {
return false;
i += 4;
} else {
return false;
}
vec.push_back(tmp);
}
vec.push_back(tmp);
}
return true;
return true;
}
template <class Uint32ContainerConIter>
void Unicode32ToUtf8(Uint32ContainerConIter begin, Uint32ContainerConIter end, string& res) {
res.clear();
uint32_t ui;
while(begin != end) {
ui = *begin;
if(ui <= 0x7f) {
res += char(ui);
} else if(ui <= 0x7ff) {
res += char(((ui >> 6) & 0x1f) | 0xc0);
res += char((ui & 0x3f) | 0x80);
} else if(ui <= 0xffff) {
res += char(((ui >> 12) & 0x0f) | 0xe0);
res += char(((ui >> 6) & 0x3f) | 0x80);
res += char((ui & 0x3f) | 0x80);
} else {
res += char(((ui >> 18) & 0x03) | 0xf0);
res += char(((ui >> 12) & 0x3f) | 0x80);
res += char(((ui >> 6) & 0x3f) | 0x80);
res += char((ui & 0x3f) | 0x80);
res.clear();
uint32_t ui;
while(begin != end) {
ui = *begin;
if(ui <= 0x7f) {
res += char(ui);
} else if(ui <= 0x7ff) {
res += char(((ui >> 6) & 0x1f) | 0xc0);
res += char((ui & 0x3f) | 0x80);
} else if(ui <= 0xffff) {
res += char(((ui >> 12) & 0x0f) | 0xe0);
res += char(((ui >> 6) & 0x3f) | 0x80);
res += char((ui & 0x3f) | 0x80);
} else {
res += char(((ui >> 18) & 0x03) | 0xf0);
res += char(((ui >> 12) & 0x3f) | 0x80);
res += char(((ui >> 6) & 0x3f) | 0x80);
res += char((ui & 0x3f) | 0x80);
}
begin ++;
}
begin ++;
}
}
template <class Uint16ContainerConIter>
void UnicodeToUtf8(Uint16ContainerConIter begin, Uint16ContainerConIter end, string& res) {
res.clear();
uint16_t ui;
while(begin != end) {
ui = *begin;
if(ui <= 0x7f) {
res += char(ui);
} else if(ui <= 0x7ff) {
res += char(((ui>>6) & 0x1f) | 0xc0);
res += char((ui & 0x3f) | 0x80);
} else {
res += char(((ui >> 12) & 0x0f )| 0xe0);
res += char(((ui>>6) & 0x3f )| 0x80 );
res += char((ui & 0x3f) | 0x80);
res.clear();
uint16_t ui;
while(begin != end) {
ui = *begin;
if(ui <= 0x7f) {
res += char(ui);
} else if(ui <= 0x7ff) {
res += char(((ui >> 6) & 0x1f) | 0xc0);
res += char((ui & 0x3f) | 0x80);
} else {
res += char(((ui >> 12) & 0x0f) | 0xe0);
res += char(((ui >> 6) & 0x3f) | 0x80);
res += char((ui & 0x3f) | 0x80);
}
begin ++;
}
begin ++;
}
}
template <class Uint16Container>
bool GBKTrans(const char* const str, size_t len, Uint16Container& vec) {
vec.clear();
if(!str) {
return true;
}
size_t i = 0;
while(i < len) {
if(0 == (str[i] & 0x80)) {
vec.push_back(uint16_t(str[i]));
i++;
} else {
if(i + 1 < len) { //&& (str[i+1] & 0x80))
uint16_t tmp = (((uint16_t(str[i]) & 0x00ff ) << 8) | (uint16_t(str[i+1]) & 0x00ff));
vec.push_back(tmp);
i += 2;
} else {
return false;
}
vec.clear();
if(!str) {
return true;
}
}
return true;
size_t i = 0;
while(i < len) {
if(0 == (str[i] & 0x80)) {
vec.push_back(uint16_t(str[i]));
i++;
} else {
if(i + 1 < len) { //&& (str[i+1] & 0x80))
uint16_t tmp = (((uint16_t(str[i]) & 0x00ff) << 8) | (uint16_t(str[i + 1]) & 0x00ff));
vec.push_back(tmp);
i += 2;
} else {
return false;
}
}
}
return true;
}
template <class Uint16Container>
bool GBKTrans(const string& str, Uint16Container& vec) {
return GBKTrans(str.c_str(), str.size(), vec);
return GBKTrans(str.c_str(), str.size(), vec);
}
template <class Uint16ContainerConIter>
void GBKTrans(Uint16ContainerConIter begin, Uint16ContainerConIter end, string& res) {
res.clear();
//pair<char, char> pa;
char first, second;
while(begin != end) {
//pa = uint16ToChar2(*begin);
first = ((*begin)>>8) & 0x00ff;
second = (*begin) & 0x00ff;
if(first & 0x80) {
res += first;
res += second;
} else {
res += second;
res.clear();
//pair<char, char> pa;
char first, second;
while(begin != end) {
//pa = uint16ToChar2(*begin);
first = ((*begin) >> 8) & 0x00ff;
second = (*begin) & 0x00ff;
if(first & 0x80) {
res += first;
res += second;
} else {
res += second;
}
begin++;
}
begin++;
}
}
/*
* format example: "%Y-%m-%d %H:%M:%S"
*/
inline void GetTime(const string& format, string& timeStr) {
time_t timeNow;
time(&timeNow);
timeStr.resize(64);
size_t len = strftime((char*)timeStr.c_str(), timeStr.size(), format.c_str(), localtime(&timeNow));
timeStr.resize(len);
time_t timeNow;
time(&timeNow);
timeStr.resize(64);
size_t len = strftime((char*)timeStr.c_str(), timeStr.size(), format.c_str(), localtime(&timeNow));
timeStr.resize(len);
}
inline string PathJoin(const string& path1, const string& path2) {
if(EndsWith(path1, "/")) {
return path1 + path2;
}
return path1 + "/" + path2;
if(EndsWith(path1, "/")) {
return path1 + path2;
}
return path1 + "/" + path2;
}
}

View File

@ -25,36 +25,36 @@
namespace limonp {
class IThread: NonCopyable {
public:
IThread(): isStarted(false), isJoined(false) {
}
virtual ~IThread() {
if(isStarted && !isJoined) {
XCHECK(!pthread_detach(thread_));
public:
IThread(): isStarted(false), isJoined(false) {
}
};
virtual ~IThread() {
if(isStarted && !isJoined) {
XCHECK(!pthread_detach(thread_));
}
};
virtual void Run() = 0;
void Start() {
XCHECK(!isStarted);
XCHECK(!pthread_create(&thread_, NULL, Worker, this));
isStarted = true;
}
void Join() {
XCHECK(!isJoined);
XCHECK(!pthread_join(thread_, NULL));
isJoined = true;
}
private:
static void * Worker(void * data) {
IThread * ptr = (IThread* ) data;
ptr->Run();
return NULL;
}
virtual void Run() = 0;
void Start() {
XCHECK(!isStarted);
XCHECK(!pthread_create(&thread_, NULL, Worker, this));
isStarted = true;
}
void Join() {
XCHECK(!isJoined);
XCHECK(!pthread_join(thread_, NULL));
isJoined = true;
}
private:
static void * Worker(void * data) {
IThread * ptr = (IThread*) data;
ptr->Run();
return NULL;
}
pthread_t thread_;
bool isStarted;
bool isJoined;
pthread_t thread_;
bool isStarted;
bool isJoined;
}; // class IThread
} // namespace limonp

View File

@ -30,73 +30,73 @@ using namespace std;
//class ThreadPool;
class ThreadPool: NonCopyable {
public:
class Worker: public IThread {
public:
Worker(ThreadPool* pool): ptThreadPool_(pool) {
assert(ptThreadPool_);
}
virtual ~Worker() {
}
virtual void Run() {
while (true) {
ClosureInterface* closure = ptThreadPool_->queue_.Pop();
if (closure == NULL) {
break;
public:
class Worker: public IThread {
public:
Worker(ThreadPool* pool): ptThreadPool_(pool) {
assert(ptThreadPool_);
}
try {
closure->Run();
} catch(std::exception& e) {
XLOG(ERROR) << e.what();
} catch(...) {
XLOG(ERROR) << " unknown exception.";
virtual ~Worker() {
}
delete closure;
}
}
private:
ThreadPool * ptThreadPool_;
}; // class Worker
ThreadPool(size_t thread_num)
: threads_(thread_num),
queue_(thread_num) {
assert(thread_num);
for(size_t i = 0; i < threads_.size(); i ++) {
threads_[i] = new Worker(this);
}
}
~ThreadPool() {
Stop();
}
virtual void Run() {
while(true) {
ClosureInterface* closure = ptThreadPool_->queue_.Pop();
if(closure == NULL) {
break;
}
try {
closure->Run();
} catch(std::exception& e) {
XLOG(ERROR) << e.what();
} catch(...) {
XLOG(ERROR) << " unknown exception.";
}
delete closure;
}
}
private:
ThreadPool * ptThreadPool_;
}; // class Worker
void Start() {
for(size_t i = 0; i < threads_.size(); i++) {
threads_[i]->Start();
ThreadPool(size_t thread_num)
: threads_(thread_num),
queue_(thread_num) {
assert(thread_num);
for(size_t i = 0; i < threads_.size(); i ++) {
threads_[i] = new Worker(this);
}
}
}
void Stop() {
for(size_t i = 0; i < threads_.size(); i ++) {
queue_.Push(NULL);
~ThreadPool() {
Stop();
}
for(size_t i = 0; i < threads_.size(); i ++) {
threads_[i]->Join();
delete threads_[i];
void Start() {
for(size_t i = 0; i < threads_.size(); i++) {
threads_[i]->Start();
}
}
void Stop() {
for(size_t i = 0; i < threads_.size(); i ++) {
queue_.Push(NULL);
}
for(size_t i = 0; i < threads_.size(); i ++) {
threads_[i]->Join();
delete threads_[i];
}
threads_.clear();
}
threads_.clear();
}
void Add(ClosureInterface* task) {
assert(task);
queue_.Push(task);
}
void Add(ClosureInterface* task) {
assert(task);
queue_.Push(task);
}
private:
friend class Worker;
private:
friend class Worker;
vector<IThread*> threads_;
BoundedBlockingQueue<ClosureInterface*> queue_;
vector<IThread*> threads_;
BoundedBlockingQueue<ClosureInterface*> queue_;
}; // class ThreadPool
} // namespace limonp

View File

@ -30,19 +30,18 @@ break;
println("+---------------------------------------------------------------+");
//read a line from a command line.
static fstring getLine( FILE *fp, fstring __dst )
{
static fstring getLine(FILE *fp, fstring __dst) {
register int c;
register fstring cs;
cs = __dst;
while ( ( c = getc( fp ) ) != EOF ) {
if ( c == '\n' ) break;
while((c = getc(fp)) != EOF) {
if(c == '\n') break;
*cs++ = c;
}
*cs = '\0';
return ( c == EOF && cs == __dst ) ? NULL : __dst;
return (c == EOF && cs == __dst) ? NULL : __dst;
}
/*static void printcode( fstring str ) {
@ -56,8 +55,7 @@ static fstring getLine( FILE *fp, fstring __dst )
}*/
//int friso_test(int argc, char **argv)
int friso_test()
{
int friso_test() {
clock_t s_time, e_time;
char line[__INPUT_LENGTH__] = {0};
@ -76,7 +74,7 @@ int friso_test()
// }
__path__ = "/usr/share/ukui-search/res/friso.ini";
if ( __path__ == NULL ) {
if(__path__ == NULL) {
println("Usage: friso -init lexicon path");
exit(0);
}
@ -90,12 +88,12 @@ int friso_test()
friso_dic_load_from_ifile( dic, __path__, __LENGTH__ );
friso_set_dic( friso, dic );
friso_set_mode( friso, __FRISO_COMPLEX_MODE__ );*/
if ( friso_init_from_ifile(friso, config, __path__) != 1 ) {
if(friso_init_from_ifile(friso, config, __path__) != 1) {
printf("fail to initialize friso and config.\n");
goto err;
}
switch ( config->mode ) {
switch(config->mode) {
case __FRISO_SIMPLE_MODE__:
mode = "Simple";
break;
@ -114,29 +112,29 @@ int friso_test()
e_time = clock();
printf("Initialized in %fsec\n", (double) ( e_time - s_time ) / CLOCKS_PER_SEC );
printf("Initialized in %fsec\n", (double)(e_time - s_time) / CLOCKS_PER_SEC);
printf("Mode: %s\n", mode);
printf("+-Version: %s (%s)\n", friso_version(), friso->charset == FRISO_UTF8 ? "UTF-8" : "GBK" );
printf("+-Version: %s (%s)\n", friso_version(), friso->charset == FRISO_UTF8 ? "UTF-8" : "GBK");
___ABOUT___;
//set the task.
task = friso_new_task();
while ( 1 ) {
while(1) {
print("friso>> ");
getLine( stdin, line );
getLine(stdin, line);
//exit the programe
if (strcasecmp( line, "quit") == 0) {
if(strcasecmp(line, "quit") == 0) {
___EXIT_INFO___
}
//for ( i = 0; i < 1000000; i++ ) {
//set the task text.
friso_set_text( task, line );
friso_set_text(task, line);
println("分词结果:");
s_time = clock();
while ( ( config->next_token( friso, config, task ) ) != NULL ) {
while((config->next_token(friso, config, task)) != NULL) {
printf(
"%s[%d, %d, %d] ",
task->token->word,
@ -148,7 +146,7 @@ int friso_test()
}
//}
e_time = clock();
printf("\nDone, cost < %fsec\n", ( (double)(e_time - s_time) ) / CLOCKS_PER_SEC );
printf("\nDone, cost < %fsec\n", ((double)(e_time - s_time)) / CLOCKS_PER_SEC);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* main interface file for friso tokenizer.
* you could modify it and re-release and free for commercial use.
*
*
* @author lionsoul<chenxin619315@gmail.com>
*/
@ -25,7 +25,7 @@
/*
* Type: friso_lex_t
* -----------
* This type used to represent the type of the lexicon.
* This type used to represent the type of the lexicon.
*/
typedef enum {
__LEX_CJK_WORDS__ = 0,
@ -47,7 +47,7 @@ typedef enum {
} friso_lex_t;
typedef friso_hash_t * friso_dic_t;
#define __FRISO_LEXICON_LENGTH__ 12
#define __FRISO_LEXICON_LENGTH__ 12
//charset that Friso now support.
@ -59,7 +59,7 @@ typedef enum {
/*
* Type: friso_mode_t
* ------------------
* use to identidy the mode that the friso use.
* use to identidy the mode that the friso use.
*/
typedef enum {
__FRISO_SIMPLE_MODE__ = 1,
@ -79,7 +79,7 @@ typedef friso_entry * friso_t;
/*
* Type: lex_entry_cdt
* -------------------
* This type used to represent the lexicon entry struct.
* This type used to represent the lexicon entry struct.
*/
#define _LEX_APPENSYN_MASK (1 << 0) //append synoyums words.
#define lex_appensyn_open(e) e->ctrlMask |= _LEX_APPENSYN_MASK
@ -123,7 +123,7 @@ typedef friso_token_entry * friso_token_t;
/*
* Type: friso_task_entry
* This type used to represent the current segmentation content.
* like the text to split, and the current index, token buffer eg....
* like the text to split, and the current index, token buffer eg....
*/
//action control mask for #FRISO_TASK_T#.
#define _TASK_CHECK_CF_MASK (1 << 0) //Wether to check the chinese fraction.
@ -166,9 +166,9 @@ struct friso_config_struct {
friso_mode_t mode; //Complex mode or simple mode
//pointer to the function to get the next token
friso_token_t (*next_token) (friso_t, struct friso_config_struct *, friso_task_t);
friso_token_t (*next_token)(friso_t, struct friso_config_struct *, friso_task_t);
//pointer to the function to get the next cjk lex_entry_t
lex_entry_t (*next_cjk ) (friso_t, struct friso_config_struct *, friso_task_t);
lex_entry_t (*next_cjk)(friso_t, struct friso_config_struct *, friso_task_t);
char kpuncs[_FRISO_KEEP_PUNC_LEN]; //keep punctuations buffer.
};
@ -181,28 +181,28 @@ typedef friso_config_entry * friso_config_t;
* Function: friso_new;
* Usage: vars = friso_new( void );
* --------------------------------
* This function used to create a new empty friso friso_t;
* This function used to create a new empty friso friso_t;
* with default value.
*/
FRISO_API friso_t friso_new( void );
FRISO_API friso_t friso_new(void);
//creat a friso entry with a default value from a configuratile file.
//@return 1 for successfully and 0 for failed.
FRISO_API int friso_init_from_ifile( friso_t, friso_config_t, fstring );
FRISO_API int friso_init_from_ifile(friso_t, friso_config_t, fstring);
/*
* Function: friso_free_vars;
* Usage: friso_free( vars );
* --------------------------
* This function is used to free the allocation of the given vars.
* This function is used to free the allocation of the given vars.
*/
FRISO_API void friso_free( friso_t );
FRISO_API void friso_free(friso_t);
/*
* Function: friso_set_dic
* Usage: dic = friso_set_dic( vars, dic );
* ----------------------------------------
* This function is used to set the dictionary for friso.
* This function is used to set the dictionary for friso.
* and firso_dic_t is the pointer of a hash table array.
*/
//FRISO_API void friso_set_dic( friso_t, friso_dic_t );
@ -217,14 +217,14 @@ do {\
* ------------------------------------
* This function is used to set the mode(complex or simple) that you want to friso to use.
*/
FRISO_API void friso_set_mode( friso_config_t, friso_mode_t );
FRISO_API void friso_set_mode(friso_config_t, friso_mode_t);
/*create a new friso configuration entry and initialize
/*create a new friso configuration entry and initialize
it with the default value.*/
FRISO_API friso_config_t friso_new_config( void );
FRISO_API friso_config_t friso_new_config(void);
//initialize the specified friso config entry with default value.
FRISO_API void friso_init_config( friso_config_t );
FRISO_API void friso_init_config(friso_config_t);
//free the specified friso configuration entry.
//FRISO_API void friso_free_config( friso_config_t );
@ -234,20 +234,20 @@ FRISO_API void friso_init_config( friso_config_t );
* Function: friso_new_task;
* Usage: segment = friso_new_task( void );
* ----------------------------------------
* This function is used to create a new friso segment type;
* This function is used to create a new friso segment type;
*/
FRISO_API friso_task_t friso_new_task( void );
FRISO_API friso_task_t friso_new_task(void);
/*
* Function: friso_free_task;
* Usage: friso_free_task( task );
* Usage: friso_free_task( task );
* -------------------------------
* This function is used to free the allocation of function friso_new_segment();
*/
FRISO_API void friso_free_task( friso_task_t );
FRISO_API void friso_free_task(friso_task_t);
//create a new friso token
FRISO_API friso_token_t friso_new_token( void );
FRISO_API friso_token_t friso_new_token(void);
//free the given friso token
//FRISO_API void friso_free_token( friso_token_t );
@ -257,16 +257,16 @@ FRISO_API friso_token_t friso_new_token( void );
* Function: friso_set_text
* Usage: friso_set_text( task, text );
* ------------------------------------
* This function is used to set the text that is going to segment.
* This function is used to set the text that is going to segment.
*/
FRISO_API void friso_set_text( friso_task_t, fstring );
FRISO_API void friso_set_text(friso_task_t, fstring);
//get the next cjk word with mmseg simple mode
FRISO_API lex_entry_t next_simple_cjk( friso_t, friso_config_t, friso_task_t );
FRISO_API lex_entry_t next_simple_cjk(friso_t, friso_config_t, friso_task_t);
//get the next cjk word with mmseg complex mode(mmseg core algorithm)
FRISO_API lex_entry_t next_complex_cjk( friso_t, friso_config_t, friso_task_t );
FRISO_API lex_entry_t next_complex_cjk(friso_t, friso_config_t, friso_task_t);
/*
* Function: next_mmseg_token
@ -275,10 +275,10 @@ FRISO_API lex_entry_t next_complex_cjk( friso_t, friso_config_t, friso_task_t );
* This function is used to get next word that friso segmented
* with a split mode of __FRISO_SIMPLE_MODE__ or __FRISO_COMPLEX_MODE__
*/
FRISO_API friso_token_t next_mmseg_token( friso_t, friso_config_t, friso_task_t );
FRISO_API friso_token_t next_mmseg_token(friso_t, friso_config_t, friso_task_t);
//__FRISO_DETECT_MODE__
FRISO_API friso_token_t next_detect_token( friso_t, friso_config_t, friso_task_t );
FRISO_API friso_token_t next_detect_token(friso_t, friso_config_t, friso_task_t);
/* }}} friso main interface define :: end*/
/* {{{ lexicon interface define :: start*/
@ -289,42 +289,42 @@ FRISO_API friso_token_t next_detect_token( friso_t, friso_config_t, friso_task_t
* -----------------------------
* This function used to create a new dictionary.(memory allocation).
*/
FRISO_API friso_dic_t friso_dic_new( void );
FRISO_API friso_dic_t friso_dic_new(void);
FRISO_API fstring file_get_line( fstring, FILE * );
FRISO_API fstring file_get_line(fstring, FILE *);
/*
* Function: friso_dic_free
* Usage: friso_dic_free( void );
* ------------------------------
* This function is used to free all the allocation of friso_dic_new.
* This function is used to free all the allocation of friso_dic_new.
*/
FRISO_API void friso_dic_free( friso_dic_t );
FRISO_API void friso_dic_free(friso_dic_t);
//create a new lexicon entry.
FRISO_API lex_entry_t new_lex_entry( fstring, friso_array_t, uint_t, uint_t, uint_t );
FRISO_API lex_entry_t new_lex_entry(fstring, friso_array_t, uint_t, uint_t, uint_t);
//free the given lexicon entry.
//free all the allocations that its synonyms word's items pointed to
//when the second arguments is 1
FRISO_API void free_lex_entry_full( lex_entry_t );
FRISO_API void free_lex_entry( lex_entry_t );
FRISO_API void free_lex_entry_full(lex_entry_t);
FRISO_API void free_lex_entry(lex_entry_t);
/*
* Function: friso_dic_load
* Usage: friso_dic_load( friso, friso_lex_t, path, length );
* Usage: friso_dic_load( friso, friso_lex_t, path, length );
* --------------------------------------------------
* This function is used to load dictionary from a given path.
* no length limit when length less than 0.
*/
FRISO_API void friso_dic_load( friso_t, friso_config_t,
friso_lex_t, fstring, uint_t );
FRISO_API void friso_dic_load(friso_t, friso_config_t,
friso_lex_t, fstring, uint_t);
/*
* load the lexicon configuration file.
* and load all the valid lexicon from the conf file.
*/
FRISO_API void friso_dic_load_from_ifile( friso_t, friso_config_t, fstring, uint_t );
FRISO_API void friso_dic_load_from_ifile(friso_t, friso_config_t, fstring, uint_t);
/*
* Function: friso_dic_match
@ -332,7 +332,7 @@ FRISO_API void friso_dic_load_from_ifile( friso_t, friso_config_t, fstring, uint
* ----------------------------------------------
* This function used to put new word into the dictionary.
*/
FRISO_API void friso_dic_add( friso_dic_t, friso_lex_t, fstring, friso_array_t );
FRISO_API void friso_dic_add(friso_dic_t, friso_lex_t, fstring, friso_array_t);
/*
* Function: friso_dic_add_with_fre
@ -340,15 +340,15 @@ FRISO_API void friso_dic_add( friso_dic_t, friso_lex_t, fstring, friso_array_t )
* -------------------------------------------------------------------
* This function used to put new word width frequency into the dictionary.
*/
FRISO_API void friso_dic_add_with_fre( friso_dic_t, friso_lex_t, fstring, friso_array_t, uint_t );
FRISO_API void friso_dic_add_with_fre(friso_dic_t, friso_lex_t, fstring, friso_array_t, uint_t);
/*
* Function: friso_dic_match
* Usage: result = friso_dic_match( dic, friso_lex_t, word );
* ----------------------------------------------------
* This function is used to check the given word is in the dictionary or not.
* This function is used to check the given word is in the dictionary or not.
*/
FRISO_API int friso_dic_match( friso_dic_t, friso_lex_t, fstring );
FRISO_API int friso_dic_match(friso_dic_t, friso_lex_t, fstring);
/*
* Function: friso_dic_get
@ -356,15 +356,15 @@ FRISO_API int friso_dic_match( friso_dic_t, friso_lex_t, fstring );
* -----------------------------------------
* This function is used to search the specified lex_entry_t.
*/
FRISO_API lex_entry_t friso_dic_get( friso_dic_t, friso_lex_t, fstring );
FRISO_API lex_entry_t friso_dic_get(friso_dic_t, friso_lex_t, fstring);
/*
* Function: friso_spec_dic_size
* Usage: friso_spec_dic_size( dic, friso_lex_t )
* This function is used to get the size of the dictionary with a specified type.
* This function is used to get the size of the dictionary with a specified type.
*/
FRISO_API uint_t friso_spec_dic_size( friso_dic_t, friso_lex_t );
FRISO_API uint_t friso_all_dic_size( friso_dic_t );
FRISO_API uint_t friso_spec_dic_size(friso_dic_t, friso_lex_t);
FRISO_API uint_t friso_all_dic_size(friso_dic_t);
/* }}} lexicon interface define :: end*/
#endif /*end ifndef*/

View File

@ -4,7 +4,7 @@
* 2. hashmap interface.
* 3. dynamaic array interface.
* 4. double link list interface.
*
*
* @author chenxin <chenxin619315@gmail.com>
*/
@ -68,45 +68,45 @@ typedef string_buffer_entry * string_buffer_t;
//FRISO_API string_buffer_t new_string_buffer( void );
#define new_string_buffer() \
new_string_buffer_with_opacity( __DEFAULT_ARRAY_LIST_OPACITY__ );
FRISO_API string_buffer_t new_string_buffer_with_opacity( uint_t );
FRISO_API string_buffer_t new_string_buffer_with_string( fstring str );
FRISO_API string_buffer_t new_string_buffer_with_opacity(uint_t);
FRISO_API string_buffer_t new_string_buffer_with_string(fstring str);
/*
* this function will copy the chars that the fstring pointed.
* to the buffer.
* this may cause the resize action of the buffer.
*/
FRISO_API void string_buffer_append( string_buffer_t, fstring );
FRISO_API void string_buffer_append_char( string_buffer_t, char );
FRISO_API void string_buffer_append(string_buffer_t, fstring);
FRISO_API void string_buffer_append_char(string_buffer_t, char);
//insert the given fstring from the specified position.
FRISO_API void string_buffer_insert( string_buffer_t, uint_t idx, fstring );
FRISO_API void string_buffer_insert(string_buffer_t, uint_t idx, fstring);
//remove the char in the specified position.
FRISO_API fstring string_buffer_remove( string_buffer_t, uint_t idx, uint_t );
FRISO_API fstring string_buffer_remove(string_buffer_t, uint_t idx, uint_t);
/*
* turn the string_buffer to a string.
* or return the buffer of the string_buffer.
*/
FRISO_API string_buffer_t string_buffer_trim( string_buffer_t );
FRISO_API string_buffer_t string_buffer_trim(string_buffer_t);
/*
* free the given fstring buffer.
* and this function will not free the allocations of the
* and this function will not free the allocations of the
* the string_buffer_t->buffer, we return it to you, if there is
* a necessary you could free it youself by calling free();
*/
FRISO_API fstring string_buffer_devote( string_buffer_t );
FRISO_API fstring string_buffer_devote(string_buffer_t);
/*
* clear the given fstring buffer.
* reset its buffer with 0 and reset its length to 0.
*/
FRISO_API void string_buffer_clear( string_buffer_t );
FRISO_API void string_buffer_clear(string_buffer_t);
//free the fstring buffer include the buffer.
FRISO_API void free_string_buffer( string_buffer_t );
FRISO_API void free_string_buffer(string_buffer_t);
/**
* fstring specified chars tokenizer functions
@ -126,28 +126,28 @@ typedef string_split_entry * string_split_t;
* create a new string_split_entry.
*
* @param source
* @return string_split_t;
* @return string_split_t;
*/
FRISO_API string_split_t new_string_split( fstring, fstring );
FRISO_API string_split_t new_string_split(fstring, fstring);
FRISO_API void string_split_reset( string_split_t, fstring, fstring );
FRISO_API void string_split_reset(string_split_t, fstring, fstring);
FRISO_API void string_split_set_source( string_split_t, fstring );
FRISO_API void string_split_set_source(string_split_t, fstring);
FRISO_API void string_split_set_delimiter( string_split_t, fstring );
FRISO_API void string_split_set_delimiter(string_split_t, fstring);
FRISO_API void free_string_split( string_split_t );
FRISO_API void free_string_split(string_split_t);
/**
* get the next split fstring, and copy the
* splited fstring into the __dst buffer .
* get the next split fstring, and copy the
* splited fstring into the __dst buffer .
*
* @param string_split_t
* @param __dst
* @return fstring (NULL if reach the end of the source
* @return fstring (NULL if reach the end of the source
* or there is no more segmentation)
*/
FRISO_API fstring string_split_next( string_split_t, fstring );
FRISO_API fstring string_split_next(string_split_t, fstring);
/* }}} */
@ -170,37 +170,37 @@ typedef friso_array_entry * friso_array_t;
#define new_array_list() new_array_list_with_opacity(__DEFAULT_ARRAY_LIST_OPACITY__)
//create a new friso dynamic array with the given opacity
FRISO_API friso_array_t new_array_list_with_opacity( uint_t );
FRISO_API friso_array_t new_array_list_with_opacity(uint_t);
/*
* free the given friso array.
* and its items, but never where the items's item to pointed to .
* and its items, but never where the items's item to pointed to .
*/
FRISO_API void free_array_list( friso_array_t );
FRISO_API void free_array_list(friso_array_t);
//add a new item to the array.
FRISO_API void array_list_add( friso_array_t, void * );
FRISO_API void array_list_add(friso_array_t, void *);
//insert a new item at a specifed position.
FRISO_API void array_list_insert( friso_array_t, uint_t, void * );
FRISO_API void array_list_insert(friso_array_t, uint_t, void *);
//get a item at a specified position.
FRISO_API void *array_list_get( friso_array_t, uint_t );
FRISO_API void *array_list_get(friso_array_t, uint_t);
/*
* set the item at a specified position.
* this will return the old value.
*/
FRISO_API void *array_list_set( friso_array_t, uint_t, void * );
FRISO_API void *array_list_set(friso_array_t, uint_t, void *);
/*
* remove the given item at a specified position.
* this will return the value of the removed item.
*/
FRISO_API void *array_list_remove( friso_array_t, uint_t );
FRISO_API void *array_list_remove(friso_array_t, uint_t);
/*trim the array list for final use.*/
FRISO_API friso_array_t array_list_trim( friso_array_t );
FRISO_API friso_array_t array_list_trim(friso_array_t);
/*
* clear the array list.
@ -208,7 +208,7 @@ FRISO_API friso_array_t array_list_trim( friso_array_t );
* but will not free the point array allocations,
* and will reset the length of it.
*/
FRISO_API friso_array_t array_list_clear( friso_array_t );
FRISO_API friso_array_t array_list_clear(friso_array_t);
//return the size of the array.
//FRISO_API uint_t array_list_size( friso_array_t );
@ -247,10 +247,10 @@ typedef struct {
typedef friso_link_entry * friso_link_t;
//create a new link list
FRISO_API friso_link_t new_link_list( void );
FRISO_API friso_link_t new_link_list(void);
//free the specified link list
FRISO_API void free_link_list( friso_link_t );
FRISO_API void free_link_list(friso_link_t);
//return the size of the current link list.
//FRISO_API uint_t link_list_size( friso_link_t );
@ -261,37 +261,37 @@ FRISO_API void free_link_list( friso_link_t );
#define link_list_empty( link ) (link->size == 0)
//clear all the nodes in the link list( except the head and the tail ).
FRISO_API friso_link_t link_list_clear( friso_link_t link );
FRISO_API friso_link_t link_list_clear(friso_link_t link);
//add a new node to the link list.(append from the tail)
FRISO_API void link_list_add( friso_link_t, void * );
FRISO_API void link_list_add(friso_link_t, void *);
//add a new node before the specified node
FRISO_API void link_list_insert_before( friso_link_t, uint_t, void * );
FRISO_API void link_list_insert_before(friso_link_t, uint_t, void *);
//get the node in the current index.
FRISO_API void *link_list_get( friso_link_t, uint_t );
FRISO_API void *link_list_get(friso_link_t, uint_t);
//modify the node in the current index.
FRISO_API void *link_list_set( friso_link_t, uint_t, void * );
FRISO_API void *link_list_set(friso_link_t, uint_t, void *);
//remove the specified link node
FRISO_API void *link_list_remove( friso_link_t, uint_t );
FRISO_API void *link_list_remove(friso_link_t, uint_t);
//remove the given node
FRISO_API void *link_list_remove_node( friso_link_t, link_node_t );
FRISO_API void *link_list_remove_node(friso_link_t, link_node_t);
//remove the node from the frist.
FRISO_API void *link_list_remove_first( friso_link_t );
FRISO_API void *link_list_remove_first(friso_link_t);
//remove the last node from the link list
FRISO_API void *link_list_remove_last( friso_link_t );
FRISO_API void *link_list_remove_last(friso_link_t);
//append a node from the end.
FRISO_API void link_list_add_last( friso_link_t, void * );
FRISO_API void link_list_add_last(friso_link_t, void *);
//add a node at the begining of the link list.
FRISO_API void link_list_add_first( friso_link_t, void * );
FRISO_API void link_list_add_first(friso_link_t, void *);
/* }}} link list interface define::end*/
@ -305,7 +305,7 @@ struct hash_entry {
};
typedef struct hash_entry friso_hash_entry;
typedef friso_hash_entry * hash_entry_t;
typedef void (*fhash_callback_fn_t)( hash_entry_t );
typedef void (*fhash_callback_fn_t)(hash_entry_t);
typedef struct {
uint_t length;
@ -324,10 +324,10 @@ typedef friso_hash_cdt * friso_hash_t;
/*
* Function: new_hash_table
* Usage: table = new_hash_table();
* --------------------------------
* --------------------------------
* this function allocates a new symbol table with no entries.
*/
FRISO_API friso_hash_t new_hash_table( void );
FRISO_API friso_hash_t new_hash_table(void);
/*
* Function: free_hash_table
@ -335,7 +335,7 @@ FRISO_API friso_hash_t new_hash_table( void );
* --------------------------------------
* this function will free all the allocation for memory.
*/
FRISO_API void free_hash_table( friso_hash_t, fhash_callback_fn_t );
FRISO_API void free_hash_table(friso_hash_t, fhash_callback_fn_t);
/*
* Function: put_new_mapping
@ -343,7 +343,7 @@ FRISO_API void free_hash_table( friso_hash_t, fhash_callback_fn_t );
* ----------------------------------------
* the function associates the specified key with the given value.
*/
FRISO_API void *hash_put_mapping( friso_hash_t, fstring, void * );
FRISO_API void *hash_put_mapping(friso_hash_t, fstring, void *);
/*
* Function: is_mapping_exists
@ -351,7 +351,7 @@ FRISO_API void *hash_put_mapping( friso_hash_t, fstring, void * );
* ----------------------------------------------
* this function check the given key mapping is exists or not.
*/
FRISO_API int hash_exist_mapping( friso_hash_t, fstring );
FRISO_API int hash_exist_mapping(friso_hash_t, fstring);
/*
* Function: get_mapping_value
@ -360,7 +360,7 @@ FRISO_API int hash_exist_mapping( friso_hash_t, fstring );
* this function return the value associated with the given key.
* UNDEFINED will be return if the mapping is not exists.
*/
FRISO_API void * hash_get_value( friso_hash_t, fstring );
FRISO_API void * hash_get_value(friso_hash_t, fstring);
/*
* Function: remove_mapping
@ -368,13 +368,13 @@ FRISO_API void * hash_get_value( friso_hash_t, fstring );
* ------------------------------------
* This function is used to remove the mapping associated with the given key.
*/
FRISO_API hash_entry_t hash_remove_mapping( friso_hash_t, fstring );
FRISO_API hash_entry_t hash_remove_mapping(friso_hash_t, fstring);
/*
* Function: get_table_size
* Usage: size = get_table_size( table );
* --------------------------------------
* This function is used to count the size of the specified table.
* This function is used to count the size of the specified table.
*/
//FRISO_API uint_t hash_get_size( friso_hash_t );
#define hash_get_size( hash ) hash->size

View File

@ -15,16 +15,15 @@
*
* @return int the bytes of the current readed word.
*/
FRISO_API int gbk_next_word(
friso_task_t task,
uint_t *idx,
fstring __word )
{
FRISO_API int gbk_next_word(
friso_task_t task,
uint_t *idx,
fstring __word) {
int c;
if ( *idx >= task->length ) return 0;
if(*idx >= task->length) return 0;
c = (uchar_t)task->text[*idx];
if ( c <= 0x80 ) {
if(c <= 0x80) {
task->bytes = 1;
} else {
task->bytes = 2;
@ -46,29 +45,27 @@ FRISO_API int gbk_next_word(
//check if the given buffer is a gbk word (ANSII string).
// included the simplified and traditional words.
FRISO_API int gbk_cn_string(char *str)
{
FRISO_API int gbk_cn_string(char *str) {
int c1 = (uchar_t) str[0];
int c2 = (uchar_t) str[1];
//GBK/2: gb2312 chinese word.
return ( ((c1 >= 0xb0 && c1 <= 0xf7)
&& (c2 >= 0xa1 && c2 <= 0xfe))
//GBK/3: extend chinese words.
|| ((c1 >= 0x81 && c1 <= 0xa0)
&& ( (c2 >= 0x40 && c2 <= 0x7e)
|| (c2 >= 0x80 && c2 <= 0xfe) ))
//GBK/4: extend chinese words.
|| ((c1 >= 0xaa && c1 <= 0xfe)
&& ( (c2 >= 0x40 && c2 <= 0xfe)
|| (c2 >= 0x80 && c2 <= 0xa0) )) );
return (((c1 >= 0xb0 && c1 <= 0xf7)
&& (c2 >= 0xa1 && c2 <= 0xfe))
//GBK/3: extend chinese words.
|| ((c1 >= 0x81 && c1 <= 0xa0)
&& ((c2 >= 0x40 && c2 <= 0x7e)
|| (c2 >= 0x80 && c2 <= 0xfe)))
//GBK/4: extend chinese words.
|| ((c1 >= 0xaa && c1 <= 0xfe)
&& ((c2 >= 0x40 && c2 <= 0xfe)
|| (c2 >= 0x80 && c2 <= 0xa0))));
}
/*check if the given char is a ASCII letter
* include all the arabic number, letters and english puntuations.*/
FRISO_API int gbk_halfwidth_en_char( char c )
{
FRISO_API int gbk_halfwidth_en_char(char c) {
int u = (uchar_t) c;
return ( u >= 32 && u <= 126 );
return (u >= 32 && u <= 126);
}
/*
@ -76,52 +73,48 @@ FRISO_API int gbk_halfwidth_en_char( char c )
* include the full-width arabic numeber, letters.
* but not the full-width puntuations.
*/
FRISO_API int gbk_fullwidth_en_char( char *str )
{
FRISO_API int gbk_fullwidth_en_char(char *str) {
int c1 = (uchar_t) str[0];
int c2 = (uchar_t) str[1];
return ( (c1 == 0xA3)
&& ( (c2 >= 0xB0 && c2 <= 0xB9) //arabic numbers.
|| ( c2 >= 0xC1 && c2 <= 0xDA ) //uppercase letters.
|| ( c2 >= 0xE1 && c2 <= 0xFA) ) ); //lowercase letters.
return ((c1 == 0xA3)
&& ((c2 >= 0xB0 && c2 <= 0xB9) //arabic numbers.
|| (c2 >= 0xC1 && c2 <= 0xDA) //uppercase letters.
|| (c2 >= 0xE1 && c2 <= 0xFA))); //lowercase letters.
}
//check if the given char is a upper case english letter.
// included the full-width and half-width letters.
FRISO_API int gbk_uppercase_letter( char *str )
{
FRISO_API int gbk_uppercase_letter(char *str) {
int c1 = (uchar_t) str[0];
int c2 = (uchar_t) str[1];
if ( c1 <= 0x80 ) { //half-width
return ( c1 >= 65 && c1 <= 90 );
if(c1 <= 0x80) { //half-width
return (c1 >= 65 && c1 <= 90);
} else { //full-width
return ( c1 == 0xa3 && ( c2 >= 0xc1 && c2 <= 0xda ) );
return (c1 == 0xa3 && (c2 >= 0xc1 && c2 <= 0xda));
}
}
//check if the given char is a lower case char.
// included the full-width and half-width letters.
FRISO_API int gbk_lowercase_letter( char *str )
{
FRISO_API int gbk_lowercase_letter(char *str) {
int c1 = (uchar_t) str[0];
int c2 = (uchar_t) str[1];
if ( c1 <= 0x80 ) { //half-width
return ( c1 >= 97 && c1 <= 122 );
if(c1 <= 0x80) { //half-width
return (c1 >= 97 && c1 <= 122);
} else { //full-width
return ( c1 == 0xa3 && ( c2 >= 0xe1 && c2 <= 0xfa ) );
return (c1 == 0xa3 && (c2 >= 0xe1 && c2 <= 0xfa));
}
}
//check if the given char is a arabic numeric.
// included the full-width and half-width arabic numeric.
FRISO_API int gbk_numeric_letter( char *str )
{
FRISO_API int gbk_numeric_letter(char *str) {
int c1 = (uchar_t) str[0];
int c2 = (uchar_t) str[1];
if ( c1 <= 0x80 ) { //half-width
return ( c1 >= 48 && c1 <= 57 );
if(c1 <= 0x80) { //half-width
return (c1 >= 48 && c1 <= 57);
} else { //full-width
return ( ( c1 == 0xa3 ) && ( c2 >= 0xb0 && c2 <= 0xb9 ) );
return ((c1 == 0xa3) && (c2 >= 0xb0 && c2 <= 0xb9));
}
}
@ -129,49 +122,47 @@ FRISO_API int gbk_numeric_letter( char *str )
* check if the given fstring is make up with numeric chars.
* both full-width,half-width numeric is ok.
*/
FRISO_API int gbk_numeric_string( char *str )
{
FRISO_API int gbk_numeric_string(char *str) {
char *s = str;
int c1 = 0;
int c2 = 0;
while ( *s != '\0' ) {
c1 = (uchar_t) (*s++);
if ( c1 <= 0x80 ) { //half-width
if ( c1 < 48 || c2 > 57 ) return 0;
while(*s != '\0') {
c1 = (uchar_t)(*s++);
if(c1 <= 0x80) { //half-width
if(c1 < 48 || c2 > 57) return 0;
} else { //full-width
if ( c1 != 0xa3 ) return 0;
c2 = (uchar_t) (*s++);
if ( c2 < 0xb0 || c2 > 0xb9 ) return 0;
if(c1 != 0xa3) return 0;
c2 = (uchar_t)(*s++);
if(c2 < 0xb0 || c2 > 0xb9) return 0;
}
}
return 1;
}
FRISO_API int gbk_decimal_string( char *str )
{
FRISO_API int gbk_decimal_string(char *str) {
int c1 = 0;
int c2 = 0;
int len = strlen(str), i, p = 0;
//point header check.
if ( str[0] == '.' || str[len - 1] == '.' ) return 0;
if(str[0] == '.' || str[len - 1] == '.') return 0;
for ( i = 0; i < len; ) {
for(i = 0; i < len;) {
c1 = (uchar_t) str[i++];
//count the number of the points.
if ( c1 == 46 ) {
if(c1 == 46) {
p++;
continue;
}
if ( c1 <= 0x80 ) { //half-width
if ( c1 < 48 || c1 > 57 ) return 0;
if(c1 <= 0x80) { //half-width
if(c1 < 48 || c1 > 57) return 0;
} else { //full-width
if ( c1 != 0xa3 ) return 0;
if(c1 != 0xa3) return 0;
c2 = (uchar_t) str[i++];
if ( c2 < 0xb0 || c2 > 0xb9 ) return 0;
if(c2 < 0xb0 || c2 > 0xb9) return 0;
}
}
@ -180,17 +171,16 @@ FRISO_API int gbk_decimal_string( char *str )
//check if the given char is a english(ASCII) letter.
// (full-width and half-width), not the punctuation/arabic of course.
FRISO_API int gbk_en_letter( char *str )
{
FRISO_API int gbk_en_letter(char *str) {
int c1 = (uchar_t) str[0];
int c2 = (uchar_t) str[1];
if ( c1 <= 0x80 ) {
return ( (c1 >= 65 && c1 <= 90) //lowercase
|| (c1 >= 97 && c1 <= 122)); //uppercase
if(c1 <= 0x80) {
return ((c1 >= 65 && c1 <= 90) //lowercase
|| (c1 >= 97 && c1 <= 122)); //uppercase
} else {
return ( (c1 == 0xa3)
&& ( ( c2 >= 0xc1 && c2 <= 0xda ) //lowercase
|| ( c2 >= 0xe1 && c2 <= 0xfa ) ) ); //uppercase
return ((c1 == 0xa3)
&& ((c2 >= 0xc1 && c2 <= 0xda) //lowercase
|| (c2 >= 0xe1 && c2 <= 0xfa))); //uppercase
}
return 0;
@ -198,65 +188,60 @@ FRISO_API int gbk_en_letter( char *str )
//check the given char is a whitespace or not.
// included full-width and half-width whitespace.
FRISO_API int gbk_whitespace( char *str )
{
FRISO_API int gbk_whitespace(char *str) {
int c1 = (uchar_t) str[0];
int c2 = (uchar_t) str[1];
if ( c1 <= 0x80 ) {
if(c1 <= 0x80) {
return (c1 == 32);
} else {
return ( c1 == 0xa3 && c2 == 0xa0 );
return (c1 == 0xa3 && c2 == 0xa0);
}
}
/* check if the given char is a letter number like 'ⅠⅡ'
*/
FRISO_API int gbk_letter_number( char *str )
{
FRISO_API int gbk_letter_number(char *str) {
int c1 = (uchar_t) str[0];
int c2 = (uchar_t) str[1];
return ( (c1 == 0xa2)
&& ( ( c2 >= 0xa1 && c2 <= 0xb0 ) //lowercase
|| ( c2 >= 0xf0 && c2 <= 0xfe ) ) ); //uppercase
return ((c1 == 0xa2)
&& ((c2 >= 0xa1 && c2 <= 0xb0) //lowercase
|| (c2 >= 0xf0 && c2 <= 0xfe))); //uppercase
}
/*
* check if the given char is a other number like ''
*/
FRISO_API int gbk_other_number( char *str )
{
FRISO_API int gbk_other_number(char *str) {
int c1 = (uchar_t) str[0];
int c2 = (uchar_t) str[1];
return ( ( c1 == 0xa2 ) && ( c2 >= 0xc5 && c2 <= 0xee ) );
return ((c1 == 0xa2) && (c2 >= 0xc5 && c2 <= 0xee));
}
//check if the given char is a english punctuation.
FRISO_API int gbk_en_punctuation( char c )
{
FRISO_API int gbk_en_punctuation(char c) {
int u = (uchar_t) c;
return ( (u > 32 && u < 48)
|| ( u > 57 && u < 65 )
|| ( u > 90 && u < 97 )
|| ( u > 122 && u < 127 ) );
return ((u > 32 && u < 48)
|| (u > 57 && u < 65)
|| (u > 90 && u < 97)
|| (u > 122 && u < 127));
}
//check the given char is a chinese punctuation.
FRISO_API int gbk_cn_punctuation( char *str )
{
FRISO_API int gbk_cn_punctuation(char *str) {
int c1 = (uchar_t) str[0];
int c2 = (uchar_t) str[1];
//full-width en punctuation.
return ( (c1 == 0xa3 && (( c2 >= 0xa1 && c2 <= 0xaf )
|| ( c2 >= 0xba && c2 <= 0xc0 )
|| ( c2 >= 0xdb && c2 <= 0xe0 )
|| ( c2 >= 0xfb && c2 <= 0xfe ) ))
//chinese punctuation.
|| (c1 == 0xa1 && ( (c2 >= 0xa1 && c2 <= 0xae)
|| ( c2 >= 0xb0 && c2 <= 0xbf ) ))
//A6 area special punctuations:" "
|| (c1 == 0xa6 && (c2 >= 0xf9 && c2 <= 0xfe))
//A8 area special punctuations: " ˊˋ˙–―‥‵℅ "
|| (c1 == 0xa8 && (c2 >= 0x40 && c2 <= 0x47)) );
return ((c1 == 0xa3 && ((c2 >= 0xa1 && c2 <= 0xaf)
|| (c2 >= 0xba && c2 <= 0xc0)
|| (c2 >= 0xdb && c2 <= 0xe0)
|| (c2 >= 0xfb && c2 <= 0xfe)))
//chinese punctuation.
|| (c1 == 0xa1 && ((c2 >= 0xa1 && c2 <= 0xae)
|| (c2 >= 0xb0 && c2 <= 0xbf)))
//A6 area special punctuations:" "
|| (c1 == 0xa6 && (c2 >= 0xf9 && c2 <= 0xfe))
//A8 area special punctuations: " ˊˋ˙–―‥‵℅ "
|| (c1 == 0xa8 && (c2 >= 0x40 && c2 <= 0x47)));
}
/* {{{
@ -292,7 +277,7 @@ FRISO_API int gbk_cn_punctuation( char *str )
/* }}} */
//check if the given english char is a full-width char or not.
//FRISO_API int gbk_fullwidth_char( char *str )
//FRISO_API int gbk_fullwidth_char( char *str )
//{
// return 1;
//}

View File

@ -15,15 +15,14 @@
*
* @return int the bytes of the current readed word.
*/
FRISO_API int utf8_next_word(
friso_task_t task,
uint_t *idx,
fstring __word )
{
if ( *idx >= task->length ) return 0;
FRISO_API int utf8_next_word(
friso_task_t task,
uint_t *idx,
fstring __word) {
if(*idx >= task->length) return 0;
//register uint_t t;
task->bytes = get_utf8_bytes( task->text[ *idx ] );
task->bytes = get_utf8_bytes(task->text[ *idx ]);
//for ( t = 0; t < task->bytes; t++ ) {
// __word[t] = task->text[ (*idx)++ ];
@ -37,7 +36,7 @@ FRISO_API int utf8_next_word(
__word[task->bytes] = '\0';
//the unicode counter was moved here from version 1.6.0
task->unicode = get_utf8_unicode( __word );
task->unicode = get_utf8_unicode(__word);
return task->bytes;
}
@ -47,12 +46,11 @@ FRISO_API int utf8_next_word(
*
* @param int
*/
FRISO_API void print_char_binary( char value )
{
FRISO_API void print_char_binary(char value) {
register uint_t t;
for ( t = 0; t < __CHAR_BYTES__; t++ ) {
if ( ( value & 0x80 ) == 0x80 ) {
for(t = 0; t < __CHAR_BYTES__; t++) {
if((value & 0x80) == 0x80) {
printf("1");
} else {
printf("0");
@ -66,15 +64,14 @@ FRISO_API void print_char_binary( char value )
* between 1 - 6.
*
* @param __char
* @return int
* @return int
*/
FRISO_API int get_utf8_bytes( char value )
{
FRISO_API int get_utf8_bytes(char value) {
register uint_t t = 0;
//one byte ascii char.
if ( ( value & 0x80 ) == 0 ) return 1;
for ( ; ( value & 0x80 ) != 0; value <<= 1 ) {
if((value & 0x80) == 0) return 1;
for(; (value & 0x80) != 0; value <<= 1) {
t++;
}
@ -83,17 +80,16 @@ FRISO_API int get_utf8_bytes( char value )
/*
* get the unicode serial of a utf-8 char.
*
*
* @param ch
* @return int.
*/
FRISO_API int get_utf8_unicode( const fstring ch )
{
int code = 0, bytes = get_utf8_bytes( *ch );
register uchar_t *bit = ( uchar_t * ) &code;
register char b1,b2,b3;
FRISO_API int get_utf8_unicode(const fstring ch) {
int code = 0, bytes = get_utf8_bytes(*ch);
register uchar_t *bit = (uchar_t *) &code;
register char b1, b2, b3;
switch ( bytes ) {
switch(bytes) {
case 1:
*bit = *ch;
break;
@ -102,7 +98,7 @@ FRISO_API int get_utf8_unicode( const fstring ch )
b2 = *(ch + 1);
*bit = (b1 << 6) + (b2 & 0x3F);
*(bit+1) = (b1 >> 2) & 0x07;
*(bit + 1) = (b1 >> 2) & 0x07;
break;
case 3:
b1 = *ch;
@ -110,7 +106,7 @@ FRISO_API int get_utf8_unicode( const fstring ch )
b3 = *(ch + 2);
*bit = (b2 << 6) + (b3 & 0x3F);
*(bit+1) = (b1 << 4) + ((b2 >> 2) & 0x0F);
*(bit + 1) = (b1 << 4) + ((b2 >> 2) & 0x0F);
break;
//ignore the ones that are larger than 3 bytes;
}
@ -119,51 +115,50 @@ FRISO_API int get_utf8_unicode( const fstring ch )
}
//turn the unicode serial to a utf-8 string.
FRISO_API int unicode_to_utf8( uint_t u, fstring __word )
{
if ( u <= 0x0000007F ) {
FRISO_API int unicode_to_utf8(uint_t u, fstring __word) {
if(u <= 0x0000007F) {
//U-00000000 - U-0000007F
//0xxxxxxx
*__word = ( u & 0x7F );
*__word = (u & 0x7F);
return 1;
} else if ( u >= 0x00000080 && u <= 0x000007FF ) {
} else if(u >= 0x00000080 && u <= 0x000007FF) {
//U-00000080 - U-000007FF
//110xxxxx 10xxxxxx
*( __word + 1 ) = ( u & 0x3F) | 0x80;
*(__word + 1) = (u & 0x3F) | 0x80;
*__word = ((u >> 6) & 0x1F) | 0xC0;
return 2;
} else if ( u >= 0x00000800 && u <= 0x0000FFFF ) {
} else if(u >= 0x00000800 && u <= 0x0000FFFF) {
//U-00000800 - U-0000FFFF
//1110xxxx 10xxxxxx 10xxxxxx
*( __word + 2 ) = ( u & 0x3F) | 0x80;
*( __word + 1 ) = ((u >> 6) & 0x3F) | 0x80;
*(__word + 2) = (u & 0x3F) | 0x80;
*(__word + 1) = ((u >> 6) & 0x3F) | 0x80;
*__word = ((u >> 12) & 0x0F) | 0xE0;
return 3;
} else if ( u >= 0x00010000 && u <= 0x001FFFFF ) {
} else if(u >= 0x00010000 && u <= 0x001FFFFF) {
//U-00010000 - U-001FFFFF
//11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
*( __word + 3 ) = ( u & 0x3F) | 0x80;
*( __word + 2 ) = ((u >> 6) & 0x3F) | 0x80;
*( __word + 1 ) = ((u >> 12) & 0x3F) | 0x80;
*(__word + 3) = (u & 0x3F) | 0x80;
*(__word + 2) = ((u >> 6) & 0x3F) | 0x80;
*(__word + 1) = ((u >> 12) & 0x3F) | 0x80;
*__word = ((u >> 18) & 0x07) | 0xF0;
return 4;
} else if ( u >= 0x00200000 && u <= 0x03FFFFFF ) {
} else if(u >= 0x00200000 && u <= 0x03FFFFFF) {
//U-00200000 - U-03FFFFFF
//111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
*( __word + 4 ) = ( u & 0x3F) | 0x80;
*( __word + 3 ) = ((u >> 6) & 0x3F) | 0x80;
*( __word + 2 ) = ((u >> 12) & 0x3F) | 0x80;
*( __word + 1 ) = ((u >> 18) & 0x3F) | 0x80;
*(__word + 4) = (u & 0x3F) | 0x80;
*(__word + 3) = ((u >> 6) & 0x3F) | 0x80;
*(__word + 2) = ((u >> 12) & 0x3F) | 0x80;
*(__word + 1) = ((u >> 18) & 0x3F) | 0x80;
*__word = ((u >> 24) & 0x03) | 0xF8;
return 5;
} else if ( u >= 0x04000000 && u <= 0x7FFFFFFF ) {
} else if(u >= 0x04000000 && u <= 0x7FFFFFFF) {
//U-04000000 - U-7FFFFFFF
//1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
*( __word + 5 ) = ( u & 0x3F) | 0x80;
*( __word + 4 ) = ((u >> 6) & 0x3F) | 0x80;
*( __word + 3 ) = ((u >> 12) & 0x3F) | 0x80;
*( __word + 2 ) = ((u >> 18) & 0x3F) | 0x80;
*( __word + 1 ) = ((u >> 24) & 0x3F) | 0x80;
*(__word + 5) = (u & 0x3F) | 0x80;
*(__word + 4) = ((u >> 6) & 0x3F) | 0x80;
*(__word + 3) = ((u >> 12) & 0x3F) | 0x80;
*(__word + 2) = ((u >> 18) & 0x3F) | 0x80;
*(__word + 1) = ((u >> 24) & 0x3F) | 0x80;
*__word = ((u >> 30) & 0x01) | 0xFC;
return 6;
}
@ -173,17 +168,17 @@ FRISO_API int unicode_to_utf8( uint_t u, fstring __word )
/*
* check the given char is a CJK char or not.
* 2E80-2EFF CJK
* 2E80-2EFF CJK
* 2F00-2FDF
* 3000-303F CJK --ignore
* 31C0-31EF CJK
* 3200-32FF CJK --ignore.
* 3300-33FF CJK
* 3400-4DBF CJK A
* 3400-4DBF CJK A
* 4DC0-4DFF
* 4E00-9FBF CJK
* 4E00-9FBF CJK
* F900-FAFF CJK
* FE30-FE4F CJK
* FE30-FE4F CJK
* FF00-FFEF ASCII --ignore (as basic latin)
*
* Japanese:
@ -195,9 +190,9 @@ FRISO_API int unicode_to_utf8( uint_t u, fstring __word )
* AC00-D7AF
* 1100-11FF
* 3130-318F
*
*
* @param ch :pointer to the char
* @return int : 1 for yes and 0 for not.
* @return int : 1 for yes and 0 for not.
*/
//Comment one of the following macro define
@ -205,44 +200,42 @@ FRISO_API int unicode_to_utf8( uint_t u, fstring __word )
#define FRISO_CJK_CHK_C
//#define FRISO_CJK_CHK_J
//#define FRISO_CJK_CHK_K
FRISO_API int utf8_cjk_string( uint_t u )
{
FRISO_API int utf8_cjk_string(uint_t u) {
int c = 0, j = 0, k = 0;
//Chinese.
#ifdef FRISO_CJK_CHK_C
c = ( ( u >= 0x4E00 && u <= 0x9FBF )
|| ( u >= 0x2E80 && u <= 0x2EFF ) || ( u >= 0x2F00 && u <= 0x2FDF )
|| ( u >= 0x31C0 && u <= 0x31EF ) //|| ( u >= 0x3200 && u <= 0x32FF )
|| ( u >= 0x3300 && u <= 0x33FF ) //|| ( u >= 0x3400 && u <= 0x4DBF )
|| ( u >= 0x4DC0 && u <= 0x4DFF ) || ( u >= 0xF900 && u <= 0xFAFF )
|| ( u >= 0xFE30 && u <= 0xFE4F ) );
c = ((u >= 0x4E00 && u <= 0x9FBF)
|| (u >= 0x2E80 && u <= 0x2EFF) || (u >= 0x2F00 && u <= 0x2FDF)
|| (u >= 0x31C0 && u <= 0x31EF) //|| ( u >= 0x3200 && u <= 0x32FF )
|| (u >= 0x3300 && u <= 0x33FF) //|| ( u >= 0x3400 && u <= 0x4DBF )
|| (u >= 0x4DC0 && u <= 0x4DFF) || (u >= 0xF900 && u <= 0xFAFF)
|| (u >= 0xFE30 && u <= 0xFE4F));
#endif
//Japanese.
#ifdef FRISO_CJK_CHK_J
j = ( ( u >= 0x3040 && u <= 0x309F )
|| ( u >= 0x30A0 && u <= 0x30FF ) || ( u >= 0x31F0 && u <= 0x31FF ) );
j = ((u >= 0x3040 && u <= 0x309F)
|| (u >= 0x30A0 && u <= 0x30FF) || (u >= 0x31F0 && u <= 0x31FF));
#endif
//Korean
#ifdef FRISO_CJK_CHK_K
k = ( ( u >= 0xAC00 && u <= 0xD7AF )
|| ( u >= 0x1100 && u <= 0x11FF ) || ( u >= 0x3130 && u <= 0x318F ) );
k = ((u >= 0xAC00 && u <= 0xD7AF)
|| (u >= 0x1100 && u <= 0x11FF) || (u >= 0x3130 && u <= 0x318F));
#endif
return ( c || j || k );
return (c || j || k);
}
/*
* check the given char is a Basic Latin letter or not.
* include all the letters and english punctuations.
*
*
* @param c
* @return int 1 for yes and 0 for not.
* @return int 1 for yes and 0 for not.
*/
FRISO_API int utf8_halfwidth_en_char( uint_t u )
{
return ( u >= 32 && u <= 126 );
FRISO_API int utf8_halfwidth_en_char(uint_t u) {
return (u >= 32 && u <= 126);
}
/*
@ -253,44 +246,39 @@ FRISO_API int utf8_halfwidth_en_char( uint_t u )
* @param c
* @return int
*/
FRISO_API int utf8_fullwidth_en_char( uint_t u )
{
return ( (u >= 65296 && u <= 65305 ) //arabic number
|| ( u >= 65313 && u <= 65338 ) //upper case letters
|| ( u >= 65345 && u <= 65370 ) ); //lower case letters
FRISO_API int utf8_fullwidth_en_char(uint_t u) {
return ((u >= 65296 && u <= 65305) //arabic number
|| (u >= 65313 && u <= 65338) //upper case letters
|| (u >= 65345 && u <= 65370)); //lower case letters
}
//check the given char is a upper case letters or not.
// included the full-width and half-width letters.
FRISO_API int utf8_uppercase_letter( uint_t u )
{
if ( u > 65280 ) u -= 65248;
return ( u >= 65 && u <= 90 );
FRISO_API int utf8_uppercase_letter(uint_t u) {
if(u > 65280) u -= 65248;
return (u >= 65 && u <= 90);
}
//check the given char is a upper case letters or not.
// included the full-width and half-width letters.
FRISO_API int utf8_lowercase_letter( uint_t u )
{
if ( u > 65280 ) u -= 65248;
return ( u >= 97 && u <= 122 );
FRISO_API int utf8_lowercase_letter(uint_t u) {
if(u > 65280) u -= 65248;
return (u >= 97 && u <= 122);
}
//check the given char is a numeric
// included the full-width and half-width arabic numeric.
FRISO_API int utf8_numeric_letter( uint_t u )
{
if ( u > 65280 ) u -= 65248; //make full-width half-width.
return ( ( u >= 48 && u <= 57 ) );
FRISO_API int utf8_numeric_letter(uint_t u) {
if(u > 65280) u -= 65248; //make full-width half-width.
return ((u >= 48 && u <= 57));
}
//check the given char is a english letter.(included the full-width)
// not the punctuation of course.
FRISO_API int utf8_en_letter( uint_t u )
{
if ( u > 65280 ) u -= 65248;
return ( ( u >= 65 && u <= 90 )
|| ( u >= 97 && u <= 122 ) );
FRISO_API int utf8_en_letter(uint_t u) {
if(u > 65280) u -= 65248;
return ((u >= 65 && u <= 90)
|| (u >= 97 && u <= 122));
}
/*
@ -310,24 +298,23 @@ FRISO_API int utf8_en_letter( uint_t u )
* 65304,
* 65305,
*/
FRISO_API int utf8_numeric_string( const fstring str )
{
FRISO_API int utf8_numeric_string(const fstring str) {
fstring s = str;
int bytes, u;
while ( *s != '\0' ) {
while(*s != '\0') {
//if ( ! utf8_numeric_letter( get_utf8_unicode( s++ ) ) ) {
// return 0;
//}
//}
//new implemention.
//@date 2013-10-14
bytes = 1;
if ( *s < 0 ) { //full-width chars.
if(*s < 0) { //full-width chars.
u = get_utf8_unicode(s);
bytes = get_utf8_bytes(*s);
if ( u < 65296 || u > 65305 ) return 0;
} else if ( *s < 48 || *s > 57 ) {
if(u < 65296 || u > 65305) return 0;
} else if(*s < 48 || *s > 57) {
return 0;
}
@ -337,25 +324,24 @@ FRISO_API int utf8_numeric_string( const fstring str )
return 1;
}
FRISO_API int utf8_decimal_string( const fstring str )
{
FRISO_API int utf8_decimal_string(const fstring str) {
int len = strlen(str), i, p = 0;
int bytes = 0, u;
if ( str[0] == '.' || str[len-1] == '.' ) return 0;
if(str[0] == '.' || str[len - 1] == '.') return 0;
for ( i = 1; i < len; bytes = 1 ) {
for(i = 1; i < len; bytes = 1) {
//count the number of char '.'
if ( str[i] == '.' ) {
if(str[i] == '.') {
i++;
p++;
continue;
} else if ( str[i] < 0 ) {
} else if(str[i] < 0) {
//full-width numeric.
u = get_utf8_unicode(str+i);
u = get_utf8_unicode(str + i);
bytes = get_utf8_bytes(str[i]);
if ( u < 65296 || u > 65305 ) return 0;
} else if ( str[i] < 48 || str[i] > 57 ) {
if(u < 65296 || u > 65305) return 0;
} else if(str[i] < 48 || str[i] > 57) {
return 0;
}
@ -367,13 +353,12 @@ FRISO_API int utf8_decimal_string( const fstring str )
/*
* check the given char is a whitespace or not.
*
*
* @param ch
* @return int 1 for yes and 0 for not.
* @return int 1 for yes and 0 for not.
*/
FRISO_API int utf8_whitespace( uint_t u )
{
if ( u == 32 || u == 12288 ) {
FRISO_API int utf8_whitespace(uint_t u) {
if(u == 32 || u == 12288) {
return 1;
}
return 0;
@ -382,17 +367,16 @@ FRISO_API int utf8_whitespace( uint_t u )
/*
* check the given char is a english punctuation.
*
*
* @param ch
* @return int
* @return int
*/
FRISO_API int utf8_en_punctuation( uint_t u )
{
FRISO_API int utf8_en_punctuation(uint_t u) {
//if ( u > 65280 ) u = u - 65248; //make full-width half-width
return ( (u > 32 && u < 48)
|| ( u > 57 && u < 65 )
|| ( u > 90 && u < 97 ) //added @2013-08-31
|| ( u > 122 && u < 127 ) );
return ((u > 32 && u < 48)
|| (u > 57 && u < 65)
|| (u > 90 && u < 97) //added @2013-08-31
|| (u > 122 && u < 127));
}
/*
@ -400,17 +384,16 @@ FRISO_API int utf8_en_punctuation( uint_t u )
* @date 2013-08-31 added.
*
* @param ch
* @return int
* @return int
*/
FRISO_API int utf8_cn_punctuation( uint_t u )
{
return ( ( u > 65280 && u < 65296 )
|| ( u > 65305 && u < 65312 )
|| ( u > 65338 && u < 65345 )
|| ( u > 65370 && u < 65382 )
//cjk symbol and punctuation.(added 2013-09-06)
//from http://www.unicode.org/charts/PDF/U3000.pdf
|| ( u >= 12289 && u <= 12319) );
FRISO_API int utf8_cn_punctuation(uint_t u) {
return ((u > 65280 && u < 65296)
|| (u > 65305 && u < 65312)
|| (u > 65338 && u < 65345)
|| (u > 65370 && u < 65382)
//cjk symbol and punctuation.(added 2013-09-06)
//from http://www.unicode.org/charts/PDF/U3000.pdf
|| (u >= 12289 && u <= 12319));
}
/*
@ -419,8 +402,7 @@ FRISO_API int utf8_cn_punctuation( uint_t u )
* @param ch
* @return int
*/
FRISO_API int utf8_letter_number( uint_t u )
{
FRISO_API int utf8_letter_number(uint_t u) {
return 0;
}
@ -430,13 +412,12 @@ FRISO_API int utf8_letter_number( uint_t u )
* @param ch
* @return int
*/
FRISO_API int utf8_other_number( uint_t u )
{
FRISO_API int utf8_other_number(uint_t u) {
return 0;
}
//A macro define has replace this.
//FRISO_API int is_en_punctuation( char c )
//FRISO_API int is_en_punctuation( char c )
//{
// return utf8_en_punctuation( (uint_t) c );
//}
@ -448,9 +429,9 @@ FRISO_API int utf8_other_number( uint_t u )
/* @Deprecated
* check the given char is an english keep punctuation.*/
//FRISO_API int utf8_keep_punctuation( fstring str )
//FRISO_API int utf8_keep_punctuation( fstring str )
//{
// if ( __keep_punctuations_hash__ == NULL )
// if ( __keep_punctuations_hash__ == NULL )
// {
// __keep_punctuations_hash__ = new_hash_table();
// hash_put_mapping( __keep_punctuations_hash__, "@", NULL );
@ -473,11 +454,11 @@ FRISO_API int utf8_other_number( uint_t u )
/*
* check the given english char is a full-width char or not.
*
*
* @param ch
* @return 1 for yes and 0 for not.
* @return 1 for yes and 0 for not.
*/
//FRISO_API int utf8_fullwidth_char( uint_t u )
//FRISO_API int utf8_fullwidth_char( uint_t u )
//{
// if ( u == 12288 )
// return 1; //full-width space

View File

@ -10,16 +10,15 @@
/* ********************************************
* friso array list static functions block *
**********************************************/
__STATIC_API__ void **create_array_entries( uint_t __blocks )
{
__STATIC_API__ void **create_array_entries(uint_t __blocks) {
register uint_t t;
void **block = ( void ** ) FRISO_CALLOC( sizeof( void * ), __blocks );
if ( block == NULL ) {
void **block = (void **) FRISO_CALLOC(sizeof(void *), __blocks);
if(block == NULL) {
___ALLOCATION_ERROR___
}
//initialize
for ( t = 0; t < __blocks; t++ ) {
for(t = 0; t < __blocks; t++) {
block[t] = NULL;
}
@ -27,18 +26,17 @@ __STATIC_API__ void **create_array_entries( uint_t __blocks )
}
//resize the array. (the opacity should not be smaller than array->length)
__STATIC_API__ friso_array_t resize_array_list(
friso_array_t array,
uint_t opacity )
{
__STATIC_API__ friso_array_t resize_array_list(
friso_array_t array,
uint_t opacity) {
register uint_t t;
void **block = create_array_entries( opacity );
void **block = create_array_entries(opacity);
for ( t = 0; t < array->length ; t++ ) {
for(t = 0; t < array->length ; t++) {
block[t] = array->items[t];
}
FRISO_FREE( array->items );
FRISO_FREE(array->items);
array->items = block;
array->allocs = opacity;
@ -55,16 +53,15 @@ __STATIC_API__ friso_array_t resize_array_list(
//}
//create a new array list with a given opacity.
FRISO_API friso_array_t new_array_list_with_opacity( uint_t opacity )
{
friso_array_t array = ( friso_array_t )
FRISO_MALLOC( sizeof( friso_array_entry ) );
if ( array == NULL ) {
FRISO_API friso_array_t new_array_list_with_opacity(uint_t opacity) {
friso_array_t array = (friso_array_t)
FRISO_MALLOC(sizeof(friso_array_entry));
if(array == NULL) {
___ALLOCATION_ERROR___
}
//initialize
array->items = create_array_entries( opacity );
array->items = create_array_entries(opacity);
array->allocs = opacity;
array->length = 0;
@ -73,10 +70,9 @@ FRISO_API friso_array_t new_array_list_with_opacity( uint_t opacity )
/*
* free the given friso array.
* and its items, but never where its items item pointed to .
* and its items, but never where its items item pointed to .
*/
FRISO_API void free_array_list( friso_array_t array )
{
FRISO_API void free_array_list(friso_array_t array) {
//free the allocation that all the items pointed to
//register int t;
//if ( flag == 1 ) {
@ -87,40 +83,38 @@ FRISO_API void free_array_list( friso_array_t array )
// }
//}
FRISO_FREE( array->items );
FRISO_FREE( array );
FRISO_FREE(array->items);
FRISO_FREE(array);
}
//add a new item to the array.
FRISO_API void array_list_add( friso_array_t array, void *value )
{
FRISO_API void array_list_add(friso_array_t array, void *value) {
//check the condition to resize.
if ( array->length == array->allocs ) {
resize_array_list( array, array->length * 2 + 1 );
if(array->length == array->allocs) {
resize_array_list(array, array->length * 2 + 1);
}
array->items[array->length++] = value;
}
//insert a new item at a specified position.
FRISO_API void array_list_insert(
friso_array_t array,
uint_t idx,
void *value )
{
FRISO_API void array_list_insert(
friso_array_t array,
uint_t idx,
void *value) {
register uint_t t;
if ( idx <= array->length ) {
if(idx <= array->length) {
//check the condition to resize the array.
if ( array->length == array->allocs ) {
resize_array_list( array, array->length * 2 + 1 );
if(array->length == array->allocs) {
resize_array_list(array, array->length * 2 + 1);
}
//move the elements after idx.
//for ( t = idx; t < array->length; t++ ) {
// array->items[t+1] = array->items[t];
//}
for ( t = array->length - 1; t >= idx; t-- ) {
array->items[t+1] = array->items[t];
for(t = array->length - 1; t >= idx; t--) {
array->items[t + 1] = array->items[t];
}
array->items[idx] = value;
@ -129,9 +123,8 @@ FRISO_API void array_list_insert(
}
//get the item at a specified position.
FRISO_API void *array_list_get( friso_array_t array, uint_t idx )
{
if ( idx < array->length ) {
FRISO_API void *array_list_get(friso_array_t array, uint_t idx) {
if(idx < array->length) {
return array->items[idx];
}
return NULL;
@ -139,13 +132,12 @@ FRISO_API void *array_list_get( friso_array_t array, uint_t idx )
//set the value of the item at a specified position.
//this will return the old value.
FRISO_API void * array_list_set(
friso_array_t array,
uint_t idx,
void * value )
{
FRISO_API void * array_list_set(
friso_array_t array,
uint_t idx,
void * value) {
void * oval = NULL;
if ( idx < array->length ) {
if(idx < array->length) {
oval = array->items[idx];
array->items[idx] = value;
}
@ -154,16 +146,15 @@ FRISO_API void * array_list_set(
//remove the item at a specified position.
//this will return the value of the removed item.
FRISO_API void * array_list_remove(
friso_array_t array, uint_t idx )
{
FRISO_API void * array_list_remove(
friso_array_t array, uint_t idx) {
register uint_t t;
void *oval = NULL;
if ( idx < array->length ) {
if(idx < array->length) {
oval = array->items[idx];
//move the elements after idx.
for ( t = idx; t < array->length - 1; t++ ) {
for(t = idx; t < array->length - 1; t++) {
array->items[t] = array->items[ t + 1 ];
}
array->items[array->length - 1] = NULL;
@ -174,11 +165,10 @@ FRISO_API void * array_list_remove(
}
/*trim the array list*/
FRISO_API friso_array_t array_list_trim( friso_array_t array )
{
if ( array->length < array->allocs ) {
return resize_array_list( array, array->length );
}
FRISO_API friso_array_t array_list_trim(friso_array_t array) {
if(array->length < array->allocs) {
return resize_array_list(array, array->length);
}
return array;
}
@ -188,20 +178,19 @@ FRISO_API friso_array_t array_list_trim( friso_array_t array )
* but will not free the point array allocations,
* and will reset the length of it.
*/
FRISO_API friso_array_t array_list_clear( friso_array_t array )
{
FRISO_API friso_array_t array_list_clear(friso_array_t array) {
register uint_t t;
//free all the allocations that the array->length's pointer pointed.
for ( t = 0; t < array->length; t++ ) {
for(t = 0; t < array->length; t++) {
/*if ( array->items[t] == NULL ) continue;
FRISO_FREE( array->items[t] ); */
array->items[t] = NULL;
array->items[t] = NULL;
}
//attribute reset.
array->length = 0;
return array;
}
}
//get the size of the array list. (A macro define has replace this.)
//FRISO_API uint_t array_list_size( friso_array_t array ) {
@ -214,7 +203,7 @@ FRISO_API friso_array_t array_list_clear( friso_array_t array )
//}
//check if the array is empty.(A macro define has replace this.)
//FRISO_API int array_list_empty( friso_array_t array )
//FRISO_API int array_list_empty( friso_array_t array )
//{
// return ( array->length == 0 );
//}

View File

@ -1,6 +1,6 @@
/**
* friso string type check functions,
* like english/CJK, full-wdith/half-width, punctuation or not.
* friso string type check functions,
* like english/CJK, full-wdith/half-width, punctuation or not.
* @see friso_UTF8.c and friso_GBK.c for detail.
*
* @author lionsoul<chenxin619315@gmail.com>
@ -13,16 +13,15 @@
#include "friso_API.h"
/* check if the specified string is a cn string.
*
*
* @return int (true for cn string or false)
* */
FRISO_API int friso_cn_string(
friso_charset_t charset,
friso_task_t task )
{
if ( charset == FRISO_UTF8 ) {
FRISO_API int friso_cn_string(
friso_charset_t charset,
friso_task_t task) {
if(charset == FRISO_UTF8) {
return utf8_cjk_string(task->unicode);
} else if ( charset == FRISO_GBK ) {
} else if(charset == FRISO_GBK) {
return gbk_cn_string(task->buffer);
}
@ -30,13 +29,12 @@ FRISO_API int friso_cn_string(
}
//check if the specified word is a whitespace.
FRISO_API int friso_whitespace(
friso_charset_t charset,
friso_task_t task )
{
if ( charset == FRISO_UTF8 ) {
FRISO_API int friso_whitespace(
friso_charset_t charset,
friso_task_t task) {
if(charset == FRISO_UTF8) {
return utf8_whitespace(task->unicode);
} else if ( charset == FRISO_GBK ) {
} else if(charset == FRISO_GBK) {
return gbk_whitespace(task->buffer);
}
@ -46,11 +44,10 @@ FRISO_API int friso_whitespace(
//check if the specifiled word is a numeric letter.
FRISO_API int friso_numeric_letter(
friso_charset_t charset,
friso_task_t task)
{
if ( charset == FRISO_UTF8 ) {
friso_task_t task) {
if(charset == FRISO_UTF8) {
return utf8_numeric_letter((uint_t) task->text[task->idx]);
} else if ( charset == FRISO_GBK ) {
} else if(charset == FRISO_GBK) {
return gbk_numeric_letter(task->text + task->idx);
}
@ -58,14 +55,13 @@ FRISO_API int friso_numeric_letter(
}
//check if the specified word is aa english letter.
FRISO_API int friso_en_letter(
friso_charset_t charset,
friso_task_t task )
{
if ( charset == FRISO_UTF8 ) {
return utf8_en_letter( ( uint_t ) task->text[task->idx]);
} else if ( charset == FRISO_GBK ) {
return gbk_en_letter( task->text + task->idx );
FRISO_API int friso_en_letter(
friso_charset_t charset,
friso_task_t task) {
if(charset == FRISO_UTF8) {
return utf8_en_letter((uint_t) task->text[task->idx]);
} else if(charset == FRISO_GBK) {
return gbk_en_letter(task->text + task->idx);
}
return 0;
@ -73,13 +69,12 @@ FRISO_API int friso_en_letter(
//check if the specified word is a half-width letter.
// punctuations are inclued.
FRISO_API int friso_halfwidth_en_char(
friso_charset_t charset,
friso_task_t task )
{
if ( charset == FRISO_UTF8 ) {
FRISO_API int friso_halfwidth_en_char(
friso_charset_t charset,
friso_task_t task) {
if(charset == FRISO_UTF8) {
return utf8_halfwidth_en_char(task->unicode);
} else if ( charset == FRISO_GBK ) {
} else if(charset == FRISO_GBK) {
return gbk_halfwidth_en_char(task->buffer[0]);
}
@ -88,14 +83,13 @@ FRISO_API int friso_halfwidth_en_char(
//check if the specified word is a full-width letter.
// full-width punctuations are not included.
FRISO_API int friso_fullwidth_en_char(
friso_charset_t charset,
friso_task_t task )
{
if ( charset == FRISO_UTF8 ) {
return utf8_fullwidth_en_char( task->unicode );
} else if ( charset == FRISO_GBK ) {
return gbk_fullwidth_en_char( task->buffer );
FRISO_API int friso_fullwidth_en_char(
friso_charset_t charset,
friso_task_t task) {
if(charset == FRISO_UTF8) {
return utf8_fullwidth_en_char(task->unicode);
} else if(charset == FRISO_GBK) {
return gbk_fullwidth_en_char(task->buffer);
}
return 0;
@ -104,49 +98,45 @@ FRISO_API int friso_fullwidth_en_char(
//check if the specified word is an english punctuations.
FRISO_API int friso_en_punctuation(
friso_charset_t charset,
friso_task_t task )
{
if ( charset == FRISO_UTF8 ) {
return utf8_en_punctuation( task->unicode );
} else if ( charset == FRISO_GBK ) {
return gbk_en_punctuation( task->buffer[0] );
friso_task_t task) {
if(charset == FRISO_UTF8) {
return utf8_en_punctuation(task->unicode);
} else if(charset == FRISO_GBK) {
return gbk_en_punctuation(task->buffer[0]);
}
return 0;
}
//check if the specified word ia sn chinese punctuation.
FRISO_API int friso_cn_punctuation(
friso_charset_t charset,
friso_task_t task )
{
if ( charset == FRISO_UTF8 ) {
return utf8_cn_punctuation( task->unicode );
} else if ( charset == FRISO_GBK ) {
return gbk_cn_punctuation( task->buffer );
FRISO_API int friso_cn_punctuation(
friso_charset_t charset,
friso_task_t task) {
if(charset == FRISO_UTF8) {
return utf8_cn_punctuation(task->unicode);
} else if(charset == FRISO_GBK) {
return gbk_cn_punctuation(task->buffer);
}
return 0;
}
FRISO_API int friso_letter_number(
friso_charset_t charset,
friso_task_t task )
{
FRISO_API int friso_letter_number(
friso_charset_t charset,
friso_task_t task) {
return 0;
}
FRISO_API int friso_other_number(
friso_charset_t charset,
friso_task_t task )
{
FRISO_API int friso_other_number(
friso_charset_t charset,
friso_task_t task) {
return 0;
}
//check if the word is a keep punctuation.
//@Deprecated
//FRISO_API int friso_keep_punctuation(
// friso_charset_t charset,
//FRISO_API int friso_keep_punctuation(
// friso_charset_t charset,
// friso_task_t task )
//{
// if ( charset == FRISO_UTF8 )
@ -158,40 +148,37 @@ FRISO_API int friso_other_number(
//check if the specified char is en english punctuation.
// this function is the same as friso_en_punctuation.
FRISO_API int is_en_punctuation(
friso_charset_t charset, char c )
{
if ( charset == FRISO_UTF8 ) {
return utf8_en_punctuation( (uint_t) c);
} else if ( charset == FRISO_GBK ) {
return gbk_en_punctuation( c );
FRISO_API int is_en_punctuation(
friso_charset_t charset, char c) {
if(charset == FRISO_UTF8) {
return utf8_en_punctuation((uint_t) c);
} else if(charset == FRISO_GBK) {
return gbk_en_punctuation(c);
}
return 0;
}
//check the specified string is make up with numeric.
FRISO_API int friso_numeric_string(
friso_charset_t charset,
char *buffer )
{
if ( charset == FRISO_UTF8 ) {
return utf8_numeric_string( buffer );
} else if ( charset == FRISO_GBK ) {
return gbk_numeric_string( buffer );
//check the specified string is make up with numeric.
FRISO_API int friso_numeric_string(
friso_charset_t charset,
char *buffer) {
if(charset == FRISO_UTF8) {
return utf8_numeric_string(buffer);
} else if(charset == FRISO_GBK) {
return gbk_numeric_string(buffer);
}
return 0;
}
//check the specified string is a decimal string.
FRISO_API int friso_decimal_string(
friso_charset_t charset, char *buffer )
{
if ( charset == FRISO_UTF8 ) {
return utf8_decimal_string( buffer );
} else if ( charset == FRISO_GBK ) {
return gbk_decimal_string( buffer );
FRISO_API int friso_decimal_string(
friso_charset_t charset, char *buffer) {
if(charset == FRISO_UTF8) {
return utf8_decimal_string(buffer);
} else if(charset == FRISO_GBK) {
return gbk_decimal_string(buffer);
}
return 0;
@ -199,14 +186,13 @@ FRISO_API int friso_decimal_string(
//check if the specified char is english uppercase letter.
// included full-width and half-width letters.
FRISO_API int friso_uppercase_letter(
friso_charset_t charset,
friso_task_t task )
{
if ( charset == FRISO_UTF8 ) {
return utf8_uppercase_letter( task->unicode );
} else if ( charset == FRISO_GBK ) {
return gbk_uppercase_letter( task->buffer );
FRISO_API int friso_uppercase_letter(
friso_charset_t charset,
friso_task_t task) {
if(charset == FRISO_UTF8) {
return utf8_uppercase_letter(task->unicode);
} else if(charset == FRISO_GBK) {
return gbk_uppercase_letter(task->buffer);
}
return 0;
@ -216,27 +202,26 @@ FRISO_API int friso_uppercase_letter(
* the type will be the constants defined above.
* (include the fullwidth english char.)
*/
FRISO_API friso_enchar_t friso_enchar_type(
friso_charset_t charset,
friso_task_t task )
{
FRISO_API friso_enchar_t friso_enchar_type(
friso_charset_t charset,
friso_task_t task) {
//Unicode or ASCII.(Both UTF-8 and GBK are valid)
uint_t u = 0;
if ( charset == FRISO_UTF8 ) {
if(charset == FRISO_UTF8) {
u = task->unicode;
//if ( u >= 65280 ) u = 65280 - 65248;
} else if ( charset == FRISO_GBK ) {
} else if(charset == FRISO_GBK) {
u = (uchar_t)task->buffer[0];
//if ( u == 0xa3 ) ; //full-width.
}
//range check.
if ( u > 126 || u < 32 ) return FRISO_EN_UNKNOW;
if ( u == 32 ) return FRISO_EN_WHITESPACE;
if ( u >= 48 && u <= 57 ) return FRISO_EN_NUMERIC;
if ( u >= 65 && u <= 90 ) return FRISO_EN_LETTER;
if ( u >= 97 && u <= 122 ) return FRISO_EN_LETTER;
if(u > 126 || u < 32) return FRISO_EN_UNKNOW;
if(u == 32) return FRISO_EN_WHITESPACE;
if(u >= 48 && u <= 57) return FRISO_EN_NUMERIC;
if(u >= 65 && u <= 90) return FRISO_EN_LETTER;
if(u >= 97 && u <= 122) return FRISO_EN_LETTER;
return FRISO_EN_PUNCTUATION;
}
@ -245,16 +230,15 @@ FRISO_API friso_enchar_t friso_enchar_type(
* the type will be the constants defined above.
* (the char should be half-width english char only)
*/
FRISO_API friso_enchar_t get_enchar_type( char ch )
{
FRISO_API friso_enchar_t get_enchar_type(char ch) {
uint_t u = (uchar_t) ch;
//range check.
if ( u > 126 || u < 32 ) return FRISO_EN_UNKNOW;
if ( u == 32 ) return FRISO_EN_WHITESPACE;
if ( u >= 48 && u <= 57 ) return FRISO_EN_NUMERIC;
if ( u >= 65 && u <= 90 ) return FRISO_EN_LETTER;
if ( u >= 97 && u <= 122 ) return FRISO_EN_LETTER;
if(u > 126 || u < 32) return FRISO_EN_UNKNOW;
if(u == 32) return FRISO_EN_WHITESPACE;
if(u >= 48 && u <= 57) return FRISO_EN_NUMERIC;
if(u >= 65 && u <= 90) return FRISO_EN_LETTER;
if(u >= 97 && u <= 122) return FRISO_EN_LETTER;
return FRISO_EN_PUNCTUATION;
}

View File

@ -19,50 +19,50 @@
/** {{{ wrap interface */
/* check if the specified string is a cn string.
*
*
* @return int (true for cn string or false)
* */
FRISO_API int friso_cn_string( friso_charset_t, friso_task_t );
FRISO_API int friso_cn_string(friso_charset_t, friso_task_t);
//check if the specified word is a whitespace.
FRISO_API int friso_whitespace( friso_charset_t, friso_task_t );
FRISO_API int friso_whitespace(friso_charset_t, friso_task_t);
//check if the specifiled word is a numeric letter.
FRISO_API int friso_numeric_letter(friso_charset_t, friso_task_t);
//check if the specified word is a english letter.
FRISO_API int friso_en_letter( friso_charset_t, friso_task_t );
FRISO_API int friso_en_letter(friso_charset_t, friso_task_t);
//check if the specified word is a half-width letter.
// punctuations are inclued.
FRISO_API int friso_halfwidth_en_char( friso_charset_t, friso_task_t );
FRISO_API int friso_halfwidth_en_char(friso_charset_t, friso_task_t);
//check if the specified word is a full-width letter.
// full-width punctuations are not included.
FRISO_API int friso_fullwidth_en_char( friso_charset_t, friso_task_t );
FRISO_API int friso_fullwidth_en_char(friso_charset_t, friso_task_t);
//check if the specified word is an english punctuations.
FRISO_API int friso_en_punctuation( friso_charset_t, friso_task_t );
FRISO_API int friso_en_punctuation(friso_charset_t, friso_task_t);
//check if the specified word ia sn chinese punctuation.
FRISO_API int friso_cn_punctuation( friso_charset_t, friso_task_t );
FRISO_API int friso_cn_punctuation(friso_charset_t, friso_task_t);
FRISO_API int friso_letter_number( friso_charset_t, friso_task_t );
FRISO_API int friso_other_number( friso_charset_t, friso_task_t );
FRISO_API int friso_letter_number(friso_charset_t, friso_task_t);
FRISO_API int friso_other_number(friso_charset_t, friso_task_t);
//check if the word is a keep punctuation.
//@Deprecated
//FRISO_API int friso_keep_punctuation( friso_charset_t, friso_task_t );
//check the specified string is numeric string.
FRISO_API int friso_numeric_string( friso_charset_t, char * );
FRISO_API int friso_numeric_string(friso_charset_t, char *);
//check the specified string is a decimal string.
FRISO_API int friso_decimal_string( friso_charset_t, char * );
FRISO_API int friso_decimal_string(friso_charset_t, char *);
//check if the specified char is english uppercase letter.
// included full-width and half-width letters.
FRISO_API int friso_uppercase_letter( friso_charset_t, friso_task_t );
FRISO_API int friso_uppercase_letter(friso_charset_t, friso_task_t);
//en char type.
@ -83,13 +83,13 @@ typedef enum {
* the type will be the constants defined above.
* (include the fullwidth english char.)
*/
FRISO_API friso_enchar_t friso_enchar_type( friso_charset_t, friso_task_t );
FRISO_API friso_enchar_t friso_enchar_type(friso_charset_t, friso_task_t);
/* get the type of the specified en char.
* the type will be the constants defined above.
* (the char should be half-width english char only)
*/
FRISO_API friso_enchar_t get_enchar_type( char );
FRISO_API friso_enchar_t get_enchar_type(char);
/* }}} */
@ -102,76 +102,76 @@ FRISO_API friso_enchar_t get_enchar_type( char );
*
* @return int the bytes of the current readed word.
*/
FRISO_API int utf8_next_word( friso_task_t, uint_t *, fstring );
FRISO_API int utf8_next_word(friso_task_t, uint_t *, fstring);
//get the bytes of a utf-8 char.
FRISO_API int get_utf8_bytes( char );
FRISO_API int get_utf8_bytes(char);
//return the unicode serial number of a given string.
FRISO_API int get_utf8_unicode( const fstring );
FRISO_API int get_utf8_unicode(const fstring);
//convert the unicode serial to a utf-8 string.
FRISO_API int unicode_to_utf8( uint_t, fstring );
FRISO_API int unicode_to_utf8(uint_t, fstring);
//check if the given char is a CJK.
FRISO_API int utf8_cjk_string( uint_t ) ;
FRISO_API int utf8_cjk_string(uint_t) ;
/*check the given char is a Basic Latin letter or not.
* include all the letters and english puntuations.*/
FRISO_API int utf8_halfwidth_en_char( uint_t );
FRISO_API int utf8_halfwidth_en_char(uint_t);
/*
* check the given char is a full-width latain or not.
* include the full-width arabic numeber, letters.
* but not the full-width puntuations.
*/
FRISO_API int utf8_fullwidth_en_char( uint_t );
FRISO_API int utf8_fullwidth_en_char(uint_t);
//check the given char is a upper case letter or not.
// included all the full-width and half-width letters.
FRISO_API int utf8_uppercase_letter( uint_t );
FRISO_API int utf8_uppercase_letter(uint_t);
//check the given char is a lower case letter or not.
// included all the full-width and half-width letters.
FRISO_API int utf8_lowercase_letter( uint_t );
FRISO_API int utf8_lowercase_letter(uint_t);
//check the given char is a numeric.
// included the full-width and half-width arabic numeric.
FRISO_API int utf8_numeric_letter( uint_t );
FRISO_API int utf8_numeric_letter(uint_t);
/*
* check if the given fstring is make up with numeric chars.
* both full-width,half-width numeric is ok.
*/
FRISO_API int utf8_numeric_string( char * );
FRISO_API int utf8_numeric_string(char *);
FRISO_API int utf8_decimal_string( char * );
FRISO_API int utf8_decimal_string(char *);
//check the given char is a english char.
//(full-width and half-width)
//not the punctuation of course.
FRISO_API int utf8_en_letter( uint_t );
FRISO_API int utf8_en_letter(uint_t);
//check the given char is a whitespace or not.
FRISO_API int utf8_whitespace( uint_t );
FRISO_API int utf8_whitespace(uint_t);
/* check if the given char is a letter number like 'ⅠⅡ'
*/
FRISO_API int utf8_letter_number( uint_t );
FRISO_API int utf8_letter_number(uint_t);
/*
* check if the given char is a other number like ''
*/
FRISO_API int utf8_other_number( uint_t );
FRISO_API int utf8_other_number(uint_t);
//check if the given char is a english punctuation.
FRISO_API int utf8_en_punctuation( uint_t ) ;
FRISO_API int utf8_en_punctuation(uint_t) ;
//check if the given char is a chinese punctuation.
FRISO_API int utf8_cn_punctuation( uint_t u );
FRISO_API int utf8_cn_punctuation(uint_t u);
FRISO_API int is_en_punctuation( friso_charset_t, char );
//#define is_en_punctuation( c ) utf8_en_punctuation((uint_t) c)
FRISO_API int is_en_punctuation(friso_charset_t, char);
//#define is_en_punctuation( c ) utf8_en_punctuation((uint_t) c)
//@Deprecated
//FRISO_API int utf8_keep_punctuation( fstring );
@ -186,67 +186,67 @@ FRISO_API int is_en_punctuation( friso_charset_t, char );
*
* @return int the bytes of the current readed word.
*/
FRISO_API int gbk_next_word( friso_task_t, uint_t *, fstring );
FRISO_API int gbk_next_word(friso_task_t, uint_t *, fstring);
//get the bytes of a utf-8 char.
FRISO_API int get_gbk_bytes( char );
FRISO_API int get_gbk_bytes(char);
//check if the given char is a gbk char (ANSII string).
FRISO_API int gbk_cn_string( char * ) ;
FRISO_API int gbk_cn_string(char *) ;
/*check if the given char is a ASCII letter
* include all the letters and english puntuations.*/
FRISO_API int gbk_halfwidth_en_char( char );
FRISO_API int gbk_halfwidth_en_char(char);
/*
* check if the given char is a full-width latain.
* include the full-width arabic numeber, letters.
* but not the full-width puntuations.
*/
FRISO_API int gbk_fullwidth_en_char( char * );
FRISO_API int gbk_fullwidth_en_char(char *);
//check if the given char is a upper case char.
// included all the full-width and half-width letters.
FRISO_API int gbk_uppercase_letter( char * );
FRISO_API int gbk_uppercase_letter(char *);
//check if the given char is a lower case char.
// included all the full-width and half-width letters.
FRISO_API int gbk_lowercase_letter( char * );
FRISO_API int gbk_lowercase_letter(char *);
//check if the given char is a numeric.
// included the full-width and half-width arabic numeric.
FRISO_API int gbk_numeric_letter( char * );
FRISO_API int gbk_numeric_letter(char *);
/*
* check if the given fstring is make up with numeric chars.
* both full-width,half-width numeric is ok.
*/
FRISO_API int gbk_numeric_string( char * );
FRISO_API int gbk_numeric_string(char *);
FRISO_API int gbk_decimal_string( char * );
FRISO_API int gbk_decimal_string(char *);
//check if the given char is a english(ASCII) char.
//(full-width and half-width)
//not the punctuation of course.
FRISO_API int gbk_en_letter( char * );
FRISO_API int gbk_en_letter(char *);
//check the specified char is a whitespace or not.
FRISO_API int gbk_whitespace( char * );
FRISO_API int gbk_whitespace(char *);
/* check if the given char is a letter number like 'ⅠⅡ'
*/
FRISO_API int gbk_letter_number( char * );
FRISO_API int gbk_letter_number(char *);
/*
* check if the given char is a other number like ''
*/
FRISO_API int gbk_other_number( char * );
FRISO_API int gbk_other_number(char *);
//check if the given char is a english punctuation.
FRISO_API int gbk_en_punctuation( char ) ;
FRISO_API int gbk_en_punctuation(char) ;
//check the given char is a chinese punctuation.
FRISO_API int gbk_cn_punctuation( char * );
FRISO_API int gbk_cn_punctuation(char *);
//cause the logic handle is the same as the utf8.
// here invoke the utf8 interface directly.

View File

@ -16,32 +16,30 @@
/* ************************
* mapping function area *
**************************/
__STATIC_API__ uint_t hash( fstring str, uint_t length )
{
__STATIC_API__ uint_t hash(fstring str, uint_t length) {
//hash code
uint_t h = 0;
while ( *str != '\0' ) {
h = h * HASH_FACTOR + ( *str++ );
while(*str != '\0') {
h = h * HASH_FACTOR + (*str++);
}
return (h % length);
}
/*test if a integer is a prime.*/
__STATIC_API__ int is_prime( int n )
{
__STATIC_API__ int is_prime(int n) {
int j;
if ( n == 2 || n == 3 ) {
if(n == 2 || n == 3) {
return 1;
}
if ( n == 1 || n % 2 == 0 ) {
if(n == 1 || n % 2 == 0) {
return 0;
}
for ( j = 3; j * j < n; j++ ) {
if ( n % j == 0 ) {
for(j = 3; j * j < n; j++) {
if(n % j == 0) {
return 0;
}
}
@ -50,10 +48,9 @@ __STATIC_API__ int is_prime( int n )
}
/*get the next prime just after the speicified integer.*/
__STATIC_API__ int next_prime( int n )
{
if ( n % 2 == 0 ) n++;
for ( ; ! is_prime( n ); n = n + 2 ) ;
__STATIC_API__ int next_prime(int n) {
if(n % 2 == 0) n++;
for(; ! is_prime(n); n = n + 2) ;
return n;
}
@ -76,14 +73,13 @@ __STATIC_API__ int next_prime( int n )
/* *********************************
* static hashtable function area. *
***********************************/
__STATIC_API__ hash_entry_t new_hash_entry(
fstring key,
void * value,
hash_entry_t next )
{
hash_entry_t e = ( hash_entry_t )
FRISO_MALLOC( sizeof( friso_hash_entry ) );
if ( e == NULL ) {
__STATIC_API__ hash_entry_t new_hash_entry(
fstring key,
void * value,
hash_entry_t next) {
hash_entry_t e = (hash_entry_t)
FRISO_MALLOC(sizeof(friso_hash_entry));
if(e == NULL) {
___ALLOCATION_ERROR___
}
@ -96,16 +92,15 @@ __STATIC_API__ hash_entry_t new_hash_entry(
}
//create blocks copy of entries.
__STATIC_API__ hash_entry_t * create_hash_entries( uint_t blocks )
{
__STATIC_API__ hash_entry_t * create_hash_entries(uint_t blocks) {
register uint_t t;
hash_entry_t *e = ( hash_entry_t * )
FRISO_CALLOC( sizeof( hash_entry_t ), blocks );
if ( e == NULL ) {
hash_entry_t *e = (hash_entry_t *)
FRISO_CALLOC(sizeof(hash_entry_t), blocks);
if(e == NULL) {
___ALLOCATION_ERROR___
}
for ( t = 0; t < blocks; t++ ) {
for(t = 0; t < blocks; t++) {
e[t] = NULL;
}
@ -113,35 +108,34 @@ __STATIC_API__ hash_entry_t * create_hash_entries( uint_t blocks )
}
//a static function to do the re-hash work.
__STATIC_API__ void rebuild_hash( friso_hash_t _hash )
{
__STATIC_API__ void rebuild_hash(friso_hash_t _hash) {
//printf("rehashed.\n");
//find the next prime as the length of the hashtable.
uint_t t, length = next_prime( _hash->length * 2 + 1 );
uint_t t, length = next_prime(_hash->length * 2 + 1);
hash_entry_t e, next, *_src = _hash->table, \
*table = create_hash_entries( length );
*table = create_hash_entries(length);
uint_t bucket;
//copy the nodes
for ( t = 0; t < _hash->length; t++ ) {
e = *( _src + t );
if ( e != NULL ) {
for(t = 0; t < _hash->length; t++) {
e = *(_src + t);
if(e != NULL) {
do {
next = e->_next;
bucket = hash( e->_key, length );
bucket = hash(e->_key, length);
e->_next = table[bucket];
table[bucket] = e;
e = next;
} while ( e != NULL );
} while(e != NULL);
}
}
_hash->table = table;
_hash->length = length;
_hash->threshold = ( uint_t ) ( _hash->length * _hash->factor );
_hash->threshold = (uint_t)(_hash->length * _hash->factor);
//free the old hash_entry_t blocks allocations.
FRISO_FREE( _src );
FRISO_FREE(_src);
}
/* ********************************
@ -149,10 +143,9 @@ __STATIC_API__ void rebuild_hash( friso_hash_t _hash )
* ********************************/
//create a new hash table.
FRISO_API friso_hash_t new_hash_table( void )
{
friso_hash_t _hash = ( friso_hash_t ) FRISO_MALLOC( sizeof ( friso_hash_cdt ) );
if ( _hash == NULL ) {
FRISO_API friso_hash_t new_hash_table(void) {
friso_hash_t _hash = (friso_hash_t) FRISO_MALLOC(sizeof(friso_hash_cdt));
if(_hash == NULL) {
___ALLOCATION_ERROR___
}
@ -160,51 +153,49 @@ FRISO_API friso_hash_t new_hash_table( void )
_hash->length = DEFAULT_LENGTH;
_hash->size = 0;
_hash->factor = DEFAULT_FACTOR;
_hash->threshold = ( uint_t ) ( _hash->length * _hash->factor );
_hash->table = create_hash_entries( _hash->length );
_hash->threshold = (uint_t)(_hash->length * _hash->factor);
_hash->table = create_hash_entries(_hash->length);
return _hash;
}
FRISO_API void free_hash_table(
friso_hash_t _hash,
fhash_callback_fn_t fentry_func )
{
FRISO_API void free_hash_table(
friso_hash_t _hash,
fhash_callback_fn_t fentry_func) {
register uint_t j;
hash_entry_t e, n;
for ( j = 0; j < _hash->length; j++ ) {
e = *( _hash->table + j );
for ( ; e != NULL ; ) {
for(j = 0; j < _hash->length; j++) {
e = *(_hash->table + j);
for(; e != NULL ;) {
n = e->_next;
if ( fentry_func != NULL ) fentry_func(e);
FRISO_FREE( e );
if(fentry_func != NULL) fentry_func(e);
FRISO_FREE(e);
e = n;
}
}
//free the pointer array block ( 4 * htable->length continuous bytes ).
FRISO_FREE( _hash->table );
FRISO_FREE( _hash );
FRISO_FREE(_hash->table);
FRISO_FREE(_hash);
}
//put a new mapping insite.
//the value cannot be NULL.
FRISO_API void *hash_put_mapping(
friso_hash_t _hash,
fstring key,
void * value )
{
uint_t bucket = ( key == NULL ) ? 0 : hash( key, _hash->length );
hash_entry_t e = *( _hash->table + bucket );
FRISO_API void *hash_put_mapping(
friso_hash_t _hash,
fstring key,
void * value) {
uint_t bucket = (key == NULL) ? 0 : hash(key, _hash->length);
hash_entry_t e = *(_hash->table + bucket);
void *oval = NULL;
//check the given key is already exists or not.
for ( ; e != NULL; e = e->_next ) {
if ( key == e->_key
|| ( key != NULL && e->_key != NULL
&& strcmp( key, e->_key ) == 0 ) ) {
for(; e != NULL; e = e->_next) {
if(key == e->_key
|| (key != NULL && e->_key != NULL
&& strcmp(key, e->_key) == 0)) {
oval = e->_val; //bak the old value
e->_key = key;
e->_val = value;
@ -213,29 +204,28 @@ FRISO_API void *hash_put_mapping(
}
//put a new mapping into the hashtable.
_hash->table[bucket] = new_hash_entry( key, value, _hash->table[bucket] );
_hash->table[bucket] = new_hash_entry(key, value, _hash->table[bucket]);
_hash->size++;
//check the condition to rebuild the hashtable.
if ( _hash->size >= _hash->threshold ) {
rebuild_hash( _hash );
if(_hash->size >= _hash->threshold) {
rebuild_hash(_hash);
}
return oval;
}
//check the existence of the mapping associated with the given key.
FRISO_API int hash_exist_mapping(
friso_hash_t _hash, fstring key )
{
uint_t bucket = ( key == NULL ) ? 0 : hash( key, _hash->length );
FRISO_API int hash_exist_mapping(
friso_hash_t _hash, fstring key) {
uint_t bucket = (key == NULL) ? 0 : hash(key, _hash->length);
hash_entry_t e;
for ( e = *( _hash->table + bucket );
e != NULL; e = e->_next ) {
if ( key == e->_key
|| ( key != NULL && e->_key != NULL
&& strcmp( key, e->_key ) == 0 )) {
for(e = *(_hash->table + bucket);
e != NULL; e = e->_next) {
if(key == e->_key
|| (key != NULL && e->_key != NULL
&& strcmp(key, e->_key) == 0)) {
return 1;
}
}
@ -244,16 +234,15 @@ FRISO_API int hash_exist_mapping(
}
//get the value associated with the given key.
FRISO_API void *hash_get_value( friso_hash_t _hash, fstring key )
{
uint_t bucket = ( key == NULL ) ? 0 : hash( key, _hash->length );
FRISO_API void *hash_get_value(friso_hash_t _hash, fstring key) {
uint_t bucket = (key == NULL) ? 0 : hash(key, _hash->length);
hash_entry_t e;
for ( e = *( _hash->table + bucket );
e != NULL; e = e->_next ) {
if ( key == e->_key
|| ( key != NULL && e->_key != NULL
&& strcmp( key, e->_key ) == 0 )) {
for(e = *(_hash->table + bucket);
e != NULL; e = e->_next) {
if(key == e->_key
|| (key != NULL && e->_key != NULL
&& strcmp(key, e->_key) == 0)) {
return e->_val;
}
}
@ -262,21 +251,20 @@ FRISO_API void *hash_get_value( friso_hash_t _hash, fstring key )
}
//remove the mapping associated with the given key.
FRISO_API hash_entry_t hash_remove_mapping(
friso_hash_t _hash, fstring key )
{
uint_t bucket = ( key == NULL ) ? 0 : hash( key, _hash->length );
FRISO_API hash_entry_t hash_remove_mapping(
friso_hash_t _hash, fstring key) {
uint_t bucket = (key == NULL) ? 0 : hash(key, _hash->length);
hash_entry_t e, prev = NULL;
hash_entry_t b;
for ( e = *( _hash->table + bucket );
e != NULL; prev = e, e = e->_next ) {
if ( key == e->_key
|| ( key != NULL && e->_key != NULL
&& strcmp( key, e->_key ) == 0 ) ) {
for(e = *(_hash->table + bucket);
e != NULL; prev = e, e = e->_next) {
if(key == e->_key
|| (key != NULL && e->_key != NULL
&& strcmp(key, e->_key) == 0)) {
b = e;
//the node located at *( htable->table + bucket )
if ( prev == NULL ) {
if(prev == NULL) {
_hash->table[bucket] = e->_next;
} else {
prev->_next = e->_next;

View File

@ -1,7 +1,7 @@
/*
* friso lexicon functions implementation.
* used to deal with the friso lexicon, like: load,remove,match...
*
*
* @author lionsoul<chenxin619315@gmail.com>
*/
@ -15,16 +15,15 @@
#define __FRISO_LEX_IFILE__ "friso.lex.ini"
//create a new lexicon
FRISO_API friso_dic_t friso_dic_new()
{
FRISO_API friso_dic_t friso_dic_new() {
register uint_t t;
friso_dic_t dic = ( friso_dic_t ) FRISO_CALLOC(
sizeof( friso_hash_t ), __FRISO_LEXICON_LENGTH__ );
if ( dic == NULL ) {
friso_dic_t dic = (friso_dic_t) FRISO_CALLOC(
sizeof(friso_hash_t), __FRISO_LEXICON_LENGTH__);
if(dic == NULL) {
___ALLOCATION_ERROR___
}
for ( t = 0; t < __FRISO_LEXICON_LENGTH__; t++ ) {
for(t = 0; t < __FRISO_LEXICON_LENGTH__; t++) {
dic[t] = new_hash_table();
}
@ -33,24 +32,23 @@ FRISO_API friso_dic_t friso_dic_new()
/**
* default callback function to invoke
* when free the friso dictionary .
* when free the friso dictionary .
*
* @date 2013-06-12
*/
__STATIC_API__ void default_fdic_callback( hash_entry_t e )
{
__STATIC_API__ void default_fdic_callback(hash_entry_t e) {
register uint_t i;
friso_array_t syn;
lex_entry_t lex = ( lex_entry_t ) e->_val;
lex_entry_t lex = (lex_entry_t) e->_val;
//free the lex->word
FRISO_FREE( lex->word );
FRISO_FREE(lex->word);
//free the lex->syn if it is not NULL
if ( lex->syn != NULL ) {
if(lex->syn != NULL) {
syn = lex->syn;
for ( i = 0; i < syn->length; i++ ) {
FRISO_FREE( syn->items[i] );
for(i = 0; i < syn->length; i++) {
FRISO_FREE(syn->items[i]);
}
free_array_list( syn );
free_array_list(syn);
}
//free the e->_val
@ -58,29 +56,27 @@ __STATIC_API__ void default_fdic_callback( hash_entry_t e )
FRISO_FREE(lex);
}
FRISO_API void friso_dic_free( friso_dic_t dic )
{
FRISO_API void friso_dic_free(friso_dic_t dic) {
register uint_t t;
for ( t = 0; t < __FRISO_LEXICON_LENGTH__; t++ ) {
for(t = 0; t < __FRISO_LEXICON_LENGTH__; t++) {
//free the hash table
free_hash_table( dic[t], default_fdic_callback );
free_hash_table(dic[t], default_fdic_callback);
}
FRISO_FREE( dic );
FRISO_FREE(dic);
}
//create a new lexicon entry
FRISO_API lex_entry_t new_lex_entry(
fstring word,
friso_array_t syn,
uint_t fre,
uint_t length,
uint_t type )
{
lex_entry_t e = ( lex_entry_t )
FRISO_MALLOC( sizeof( lex_entry_cdt ) );
if ( e == NULL ) {
FRISO_API lex_entry_t new_lex_entry(
fstring word,
friso_array_t syn,
uint_t fre,
uint_t length,
uint_t type) {
lex_entry_t e = (lex_entry_t)
FRISO_MALLOC(sizeof(lex_entry_cdt));
if(e == NULL) {
___ALLOCATION_ERROR___
}
@ -107,20 +103,19 @@ FRISO_API lex_entry_t new_lex_entry(
* 3. free its pos. (friso_array_t)
* 4. free the lex_entry_t.
*/
FRISO_API void free_lex_entry_full( lex_entry_t e )
{
FRISO_API void free_lex_entry_full(lex_entry_t e) {
register uint_t i;
friso_array_t syn;
//free the lex->word
FRISO_FREE( e->word );
FRISO_FREE(e->word);
//free the lex->syn if it is not NULL
if ( e->syn != NULL ) {
if(e->syn != NULL) {
syn = e->syn;
for ( i = 0; i < syn->length; i++ ) {
FRISO_FREE( syn->items[i] );
for(i = 0; i < syn->length; i++) {
FRISO_FREE(syn->items[i]);
}
free_array_list( syn );
free_array_list(syn);
}
//free the e->_val
@ -128,8 +123,7 @@ FRISO_API void free_lex_entry_full( lex_entry_t e )
FRISO_FREE(e);
}
FRISO_API void free_lex_entry( lex_entry_t e )
{
FRISO_API void free_lex_entry(lex_entry_t e) {
//if ( e->syn != NULL ) {
// if ( flag == 1 ) free_array_list( e->syn);
// else free_array_list( e->syn );
@ -140,37 +134,35 @@ FRISO_API void free_lex_entry( lex_entry_t e )
//add a new entry to the dictionary.
FRISO_API void friso_dic_add(
friso_dic_t dic,
friso_lex_t lex,
fstring word,
friso_array_t syn )
{
FRISO_API void friso_dic_add(
friso_dic_t dic,
friso_lex_t lex,
fstring word,
friso_array_t syn) {
void *olex = NULL;
if ( lex >= 0 && lex < __FRISO_LEXICON_LENGTH__ ) {
if(lex >= 0 && lex < __FRISO_LEXICON_LENGTH__) {
//printf("lex=%d, word=%s, syn=%s\n", lex, word, syn);
olex = hash_put_mapping( dic[lex], word,
new_lex_entry( word, syn, 0,
(uint_t) strlen(word), (uint_t) lex ) );
if ( olex != NULL ) {
olex = hash_put_mapping(dic[lex], word,
new_lex_entry(word, syn, 0,
(uint_t) strlen(word), (uint_t) lex));
if(olex != NULL) {
free_lex_entry_full((lex_entry_t)olex);
}
}
}
FRISO_API void friso_dic_add_with_fre(
friso_dic_t dic,
friso_lex_t lex,
fstring word,
friso_array_t syn,
uint_t frequency )
{
FRISO_API void friso_dic_add_with_fre(
friso_dic_t dic,
friso_lex_t lex,
fstring word,
friso_array_t syn,
uint_t frequency) {
void *olex = NULL;
if ( lex >= 0 && lex < __FRISO_LEXICON_LENGTH__ ) {
olex = hash_put_mapping( dic[lex], word,
new_lex_entry( word, syn, frequency,
( uint_t ) strlen(word), ( uint_t ) lex ) );
if ( olex != NULL ) {
if(lex >= 0 && lex < __FRISO_LEXICON_LENGTH__) {
olex = hash_put_mapping(dic[lex], word,
new_lex_entry(word, syn, frequency,
(uint_t) strlen(word), (uint_t) lex));
if(olex != NULL) {
free_lex_entry_full((lex_entry_t)olex);
}
}
@ -179,39 +171,37 @@ FRISO_API void friso_dic_add_with_fre(
/*
* read a line from a specified stream.
* the newline will be cleared.
*
* @date 2012-11-24
*
* @date 2012-11-24
*/
FRISO_API fstring file_get_line( fstring __dst, FILE * _stream )
{
FRISO_API fstring file_get_line(fstring __dst, FILE * _stream) {
register int c;
fstring cs;
cs = __dst;
while ( ( c = fgetc( _stream ) ) != EOF ) {
if ( c == '\n' ) break;
*cs++ = c;
while((c = fgetc(_stream)) != EOF) {
if(c == '\n') break;
*cs++ = c;
}
*cs = '\0';
return ( c == EOF && cs == __dst ) ? NULL : __dst;
return (c == EOF && cs == __dst) ? NULL : __dst;
}
/*
* static function to copy a string.
* static function to copy a string.
*/
///instead of memcpy
__STATIC_API__ fstring string_copy(
fstring _src,
fstring __dst,
uint_t blocks )
{
__STATIC_API__ fstring string_copy(
fstring _src,
fstring __dst,
uint_t blocks) {
register fstring __src = _src;
register uint_t t;
for ( t = 0; t < blocks; t++ ) {
if ( *__src == '\0' ) break;
for(t = 0; t < blocks; t++) {
if(*__src == '\0') break;
__dst[t] = *__src++;
}
__dst[t] = '\0';
@ -220,24 +210,23 @@ __STATIC_API__ fstring string_copy(
}
/**
* make a heap allocation, and copy the
* source fstring to the new allocation, and
* you should free it after use it .
* make a heap allocation, and copy the
* source fstring to the new allocation, and
* you should free it after use it .
*
* @param _src source fstring
* @param blocks number of bytes to copy
*/
__STATIC_API__ fstring string_copy_heap(
fstring _src, uint_t blocks )
{
__STATIC_API__ fstring string_copy_heap(
fstring _src, uint_t blocks) {
register uint_t t;
fstring str = ( fstring ) FRISO_MALLOC( blocks + 1 );
if ( str == NULL ) {
fstring str = (fstring) FRISO_MALLOC(blocks + 1);
if(str == NULL) {
___ALLOCATION_ERROR___;
}
for ( t = 0; t < blocks; t++ ) {
for(t = 0; t < blocks; t++) {
//if ( *_src == '\0' ) break;
str[t] = *_src++;
}
@ -249,15 +238,14 @@ __STATIC_API__ fstring string_copy_heap(
/*
* find the postion of the first appear of the given char.
* address of the char in the fstring will be return .
* if not found NULL will be return .
* if not found NULL will be return .
*/
__STATIC_API__ fstring indexOf( fstring __str, char delimiter )
{
__STATIC_API__ fstring indexOf(fstring __str, char delimiter) {
uint_t i, __length__;
__length__ = strlen( __str );
for ( i = 0; i < __length__; i++ ) {
if ( __str[i] == delimiter ) {
__length__ = strlen(__str);
for(i = 0; i < __length__; i++) {
if(__str[i] == delimiter) {
return __str + i;
}
}
@ -266,20 +254,19 @@ __STATIC_API__ fstring indexOf( fstring __str, char delimiter )
}
/**
* load all the valid wors from a specified lexicon file .
* load all the valid wors from a specified lexicon file .
*
* @param dic friso dictionary instance (A hash array)
* @param lex the lexicon type
* @param lex_file the path of the lexicon file
* @param length the maximum length of the word item
*/
FRISO_API void friso_dic_load(
friso_t friso,
friso_config_t config,
friso_lex_t lex,
fstring lex_file,
uint_t length )
{
FRISO_API void friso_dic_load(
friso_t friso,
friso_config_t config,
friso_lex_t lex,
fstring lex_file,
uint_t length) {
FILE * _stream;
char __char[1024], _buffer[512];
@ -292,35 +279,35 @@ FRISO_API void friso_dic_load(
friso_array_t sywords;
uint_t _fre;
if ( ( _stream = fopen( lex_file, "rb" ) ) != NULL ) {
while ( ( _line = file_get_line( __char, _stream ) ) != NULL ) {
if((_stream = fopen(lex_file, "rb")) != NULL) {
while((_line = file_get_line(__char, _stream)) != NULL) {
//clear up the notes
//make sure the length of the line is greater than 1.
//like the single '#' mark in stopwords dictionary.
if ( _line[0] == '#' && strlen(_line) > 1 ) continue;
if(_line[0] == '#' && strlen(_line) > 1) continue;
//handle the stopwords.
if ( lex == __LEX_STOPWORDS__ ) {
if(lex == __LEX_STOPWORDS__) {
//clean the chinese words that its length is greater than max length.
if ( ((int)_line[0]) < 0 && strlen( _line ) > length ) continue;
friso_dic_add( friso->dic, __LEX_STOPWORDS__,
string_copy_heap( _line, strlen(_line) ), NULL );
if(((int)_line[0]) < 0 && strlen(_line) > length) continue;
friso_dic_add(friso->dic, __LEX_STOPWORDS__,
string_copy_heap(_line, strlen(_line)), NULL);
continue;
}
//split the fstring with '/'.
string_split_reset( &sse, "/", _line);
if ( string_split_next( &sse, _buffer ) == NULL ) {
string_split_reset(&sse, "/", _line);
if(string_split_next(&sse, _buffer) == NULL) {
continue;
}
//1. get the word.
_word = string_copy_heap( _buffer, strlen(_buffer) );
_word = string_copy_heap(_buffer, strlen(_buffer));
if ( string_split_next( &sse, _buffer ) == NULL ) {
//normal lexicon type,
if(string_split_next(&sse, _buffer) == NULL) {
//normal lexicon type,
//add them to the dictionary directly
friso_dic_add( friso->dic, lex, _word, NULL );
friso_dic_add(friso->dic, lex, _word, NULL);
continue;
}
@ -330,87 +317,86 @@ FRISO_API void friso_dic_load(
* but not for __LEX_ECM_WORDS__ and english __LEX_STOPWORDS__
* and __LEX_CEM_WORDS__.
*/
if ( ! ( lex == __LEX_ECM_WORDS__ || lex == __LEX_CEM_WORDS__ )
&& strlen( _word ) > length ) {
if(!(lex == __LEX_ECM_WORDS__ || lex == __LEX_CEM_WORDS__)
&& strlen(_word) > length) {
FRISO_FREE(_word);
continue;
}
//2. get the synonyms words.
_syn = NULL;
if ( strcmp( _buffer, "null" ) != 0 ) {
_syn = string_copy( _buffer, _sbuffer, strlen(_buffer) );
if(strcmp(_buffer, "null") != 0) {
_syn = string_copy(_buffer, _sbuffer, strlen(_buffer));
}
//3. get the word frequency if it available.
_fre = 0;
if ( string_split_next( &sse, _buffer ) != NULL ) {
_fre = atoi( _buffer );
if(string_split_next(&sse, _buffer) != NULL) {
_fre = atoi(_buffer);
}
/**
* Here:
* split the synonyms words with mark ","
* split the synonyms words with mark ","
* and put them in a array list if the synonyms is not NULL
*/
sywords = NULL;
if ( config->add_syn && _syn != NULL ) {
string_split_reset( &sse, ",", _sbuffer );
if(config->add_syn && _syn != NULL) {
string_split_reset(&sse, ",", _sbuffer);
sywords = new_array_list_with_opacity(5);
while ( string_split_next( &sse, _buffer ) != NULL ) {
if ( strlen(_buffer) > length ) continue;
array_list_add( sywords,
string_copy_heap(_buffer, strlen(_buffer)) );
while(string_split_next(&sse, _buffer) != NULL) {
if(strlen(_buffer) > length) continue;
array_list_add(sywords,
string_copy_heap(_buffer, strlen(_buffer)));
}
sywords = array_list_trim( sywords );
sywords = array_list_trim(sywords);
}
//4. add the word item
friso_dic_add_with_fre(
friso->dic, lex, _word, sywords, _fre );
}
friso_dic_add_with_fre(
friso->dic, lex, _word, sywords, _fre);
}
fclose( _stream );
fclose(_stream);
} else {
fprintf(stderr, "Warning: Fail to open lexicon file %s\n", lex_file);
fprintf(stderr, "Warning: Without lexicon file, segment results will not correct \n");
}
}
}
/**
* get the lexicon type index with the specified
* type keywords .
* get the lexicon type index with the specified
* type keywords .
*
* @see friso.h#friso_lex_t
* @param _key
* @return int
*/
__STATIC_API__ friso_lex_t get_lexicon_type_with_constant( fstring _key )
{
if ( strcmp( _key, "__LEX_CJK_WORDS__" ) == 0 ) {
__STATIC_API__ friso_lex_t get_lexicon_type_with_constant(fstring _key) {
if(strcmp(_key, "__LEX_CJK_WORDS__") == 0) {
return __LEX_CJK_WORDS__;
} else if ( strcmp( _key, "__LEX_CJK_UNITS__" ) == 0 ) {
} else if(strcmp(_key, "__LEX_CJK_UNITS__") == 0) {
return __LEX_CJK_UNITS__;
} else if ( strcmp( _key, "__LEX_ECM_WORDS__" ) == 0 ) {
} else if(strcmp(_key, "__LEX_ECM_WORDS__") == 0) {
return __LEX_ECM_WORDS__;
} else if ( strcmp( _key, "__LEX_CEM_WORDS__" ) == 0 ) {
} else if(strcmp(_key, "__LEX_CEM_WORDS__") == 0) {
return __LEX_CEM_WORDS__;
} else if ( strcmp( _key, "__LEX_CN_LNAME__" ) == 0 ) {
} else if(strcmp(_key, "__LEX_CN_LNAME__") == 0) {
return __LEX_CN_LNAME__;
} else if ( strcmp( _key, "__LEX_CN_SNAME__" ) == 0 ) {
} else if(strcmp(_key, "__LEX_CN_SNAME__") == 0) {
return __LEX_CN_SNAME__;
} else if ( strcmp( _key, "__LEX_CN_DNAME1__" ) == 0 ) {
} else if(strcmp(_key, "__LEX_CN_DNAME1__") == 0) {
return __LEX_CN_DNAME1__;
} else if ( strcmp( _key, "__LEX_CN_DNAME2__" ) == 0 ) {
} else if(strcmp(_key, "__LEX_CN_DNAME2__") == 0) {
return __LEX_CN_DNAME2__;
} else if ( strcmp( _key, "__LEX_CN_LNA__" ) == 0 ) {
} else if(strcmp(_key, "__LEX_CN_LNA__") == 0) {
return __LEX_CN_LNA__;
} else if ( strcmp( _key, "__LEX_STOPWORDS__" ) == 0 ) {
} else if(strcmp(_key, "__LEX_STOPWORDS__") == 0) {
return __LEX_STOPWORDS__;
} else if ( strcmp( _key, "__LEX_ENPUN_WORDS__" ) == 0 ) {
} else if(strcmp(_key, "__LEX_ENPUN_WORDS__") == 0) {
return __LEX_ENPUN_WORDS__;
} else if ( strcmp( _key, "__LEX_EN_WORDS__" ) == 0 ) {
} else if(strcmp(_key, "__LEX_EN_WORDS__") == 0) {
return __LEX_EN_WORDS__;
}
@ -424,14 +410,13 @@ __STATIC_API__ friso_lex_t get_lexicon_type_with_constant( fstring _key )
* @param friso friso instance
* @param config friso_config instance
* @param _path dictionary directory
* @param _limitts words length limit
* @param _limitts words length limit
*/
FRISO_API void friso_dic_load_from_ifile(
friso_t friso,
friso_config_t config,
fstring _path,
uint_t _limits )
{
FRISO_API void friso_dic_load_from_ifile(
friso_t friso,
friso_config_t config,
fstring _path,
uint_t _limits) {
//1.parse the configuration file.
FILE *__stream;
@ -443,116 +428,112 @@ FRISO_API void friso_dic_load_from_ifile(
//get the lexicon configruation file path
sb = new_string_buffer();
string_buffer_append( sb, _path );
string_buffer_append( sb, __FRISO_LEX_IFILE__ );
string_buffer_append(sb, _path);
string_buffer_append(sb, __FRISO_LEX_IFILE__);
//printf("%s\n", sb->buffer);
if ( ( __stream = fopen( sb->buffer, "rb" ) ) != NULL ) {
while ( ( __line__ =
file_get_line( __chars__, __stream ) ) != NULL ) {
if((__stream = fopen(sb->buffer, "rb")) != NULL) {
while((__line__ =
file_get_line(__chars__, __stream)) != NULL) {
//comment filter.
if ( __line__[0] == '#' ) continue;
if ( __line__[0] == '\0' ) continue;
if(__line__[0] == '#') continue;
if(__line__[0] == '\0') continue;
__length__ = strlen( __line__ );
__length__ = strlen(__line__);
//item start
if ( __line__[ __length__ - 1 ] == '[' ) {
if(__line__[ __length__ - 1 ] == '[') {
//get the type key
for ( i = 0; i < __length__
&& ( __line__[i] == ' ' || __line__[i] == '\t' ); i++ );
for ( t = 0; i < __length__; i++,t++ ) {
if ( __line__[i] == ' '
|| __line__[i] == '\t' || __line__[i] == ':' ) break;
for(i = 0; i < __length__
&& (__line__[i] == ' ' || __line__[i] == '\t'); i++);
for(t = 0; i < __length__; i++, t++) {
if(__line__[i] == ' '
|| __line__[i] == '\t' || __line__[i] == ':') break;
__key__[t] = __line__[i];
}
__key__[t] = '\0';
//get the lexicon type
lex_t = get_lexicon_type_with_constant(__key__);
if ( lex_t == -1 ) continue;
if(lex_t == -1) continue;
//printf("key=%s, type=%d\n", __key__, lex_t );
while ( ( __line__ = file_get_line( __chars__, __stream ) ) != NULL ) {
while((__line__ = file_get_line(__chars__, __stream)) != NULL) {
//comments filter.
if ( __line__[0] == '#' ) continue;
if ( __line__[0] == '\0' ) continue;
if(__line__[0] == '#') continue;
if(__line__[0] == '\0') continue;
__length__ = strlen( __line__ );
if ( __line__[ __length__ - 1 ] == ']' ) break;
__length__ = strlen(__line__);
if(__line__[ __length__ - 1 ] == ']') break;
for ( i = 0; i < __length__
&& ( __line__[i] == ' ' || __line__[i] == '\t' ); i++ );
for ( t = 0; i < __length__; i++,t++ ) {
if ( __line__[i] == ' '
|| __line__[i] == '\t' || __line__[i] == ';' ) break;
__key__[t] = __line__[i];
for(i = 0; i < __length__
&& (__line__[i] == ' ' || __line__[i] == '\t'); i++);
for(t = 0; i < __length__; i++, t++) {
if(__line__[i] == ' '
|| __line__[i] == '\t' || __line__[i] == ';') break;
__key__[t] = __line__[i];
}
__key__[t] = '\0';
//load the lexicon item from the lexicon file.
string_buffer_clear( sb );
string_buffer_append( sb, _path );
string_buffer_append( sb, __key__ );
string_buffer_clear(sb);
string_buffer_append(sb, _path);
string_buffer_append(sb, __key__);
//printf("key=%s, type=%d\n", __key__, lex_t);
friso_dic_load( friso, config, lex_t, sb->buffer, _limits );
friso_dic_load(friso, config, lex_t, sb->buffer, _limits);
}
}
}
} //end while
fclose( __stream );
fclose(__stream);
} else {
fprintf(stderr, "Warning: Fail to open the lexicon configuration file %s\n", sb->buffer);
fprintf(stderr, "Warning: Without lexicon file, segment results will not correct \n");
}
free_string_buffer(sb);
free_string_buffer(sb);
}
//match the item.
FRISO_API int friso_dic_match(
friso_dic_t dic,
friso_lex_t lex,
fstring word )
{
if ( lex >= 0 && lex < __FRISO_LEXICON_LENGTH__ ) {
return hash_exist_mapping( dic[lex], word );
FRISO_API int friso_dic_match(
friso_dic_t dic,
friso_lex_t lex,
fstring word) {
if(lex >= 0 && lex < __FRISO_LEXICON_LENGTH__) {
return hash_exist_mapping(dic[lex], word);
}
return 0;
}
//get the lex_entry_t associated with the word.
FRISO_API lex_entry_t friso_dic_get(
friso_dic_t dic,
friso_lex_t lex,
fstring word )
{
if ( lex >= 0 && lex < __FRISO_LEXICON_LENGTH__ ) {
return ( lex_entry_t ) hash_get_value( dic[lex], word );
FRISO_API lex_entry_t friso_dic_get(
friso_dic_t dic,
friso_lex_t lex,
fstring word) {
if(lex >= 0 && lex < __FRISO_LEXICON_LENGTH__) {
return (lex_entry_t) hash_get_value(dic[lex], word);
}
return NULL;
}
//get the size of the specified type dictionary.
FRISO_API uint_t friso_spec_dic_size(
friso_dic_t dic,
friso_lex_t lex )
{
if ( lex >= 0 && lex < __FRISO_LEXICON_LENGTH__ ) {
return hash_get_size( dic[lex] );
FRISO_API uint_t friso_spec_dic_size(
friso_dic_t dic,
friso_lex_t lex) {
if(lex >= 0 && lex < __FRISO_LEXICON_LENGTH__) {
return hash_get_size(dic[lex]);
}
return 0;
}
//get size of the whole dictionary.
FRISO_API uint_t friso_all_dic_size(
friso_dic_t dic )
{
FRISO_API uint_t friso_all_dic_size(
friso_dic_t dic) {
register uint_t size = 0, t;
for ( t = 0; t < __FRISO_LEXICON_LENGTH__; t++ ) {
size += hash_get_size( dic[t] );
for(t = 0; t < __FRISO_LEXICON_LENGTH__; t++) {
size += hash_get_size(dic[t]);
}
return size;

View File

@ -10,14 +10,13 @@
#include <stdlib.h>
//create a new link list node.
__STATIC_API__ link_node_t new_node_entry(
void * value,
link_node_t prev,
link_node_t next )
{
link_node_t node = ( link_node_t )
FRISO_MALLOC( sizeof( link_node_entry ) );
if ( node == NULL ) {
__STATIC_API__ link_node_t new_node_entry(
void * value,
link_node_t prev,
link_node_t next) {
link_node_t node = (link_node_t)
FRISO_MALLOC(sizeof(link_node_entry));
if(node == NULL) {
___ALLOCATION_ERROR___
}
@ -29,17 +28,16 @@ __STATIC_API__ link_node_t new_node_entry(
}
//create a new link list
FRISO_API friso_link_t new_link_list( void )
{
friso_link_t e = ( friso_link_t )
FRISO_MALLOC( sizeof( friso_link_entry ) );
if ( e == NULL ) {
FRISO_API friso_link_t new_link_list(void) {
friso_link_t e = (friso_link_t)
FRISO_MALLOC(sizeof(friso_link_entry));
if(e == NULL) {
___ALLOCATION_ERROR___
}
//initialize the entry
e->head = new_node_entry( NULL, NULL, NULL );
e->tail = new_node_entry( NULL, e->head, NULL );
e->head = new_node_entry(NULL, NULL, NULL);
e->tail = new_node_entry(NULL, e->head, NULL);
e->head->next = e->tail;
e->size = 0;
@ -47,28 +45,25 @@ FRISO_API friso_link_t new_link_list( void )
}
//free the given link list
FRISO_API void free_link_list( friso_link_t link )
{
FRISO_API void free_link_list(friso_link_t link) {
link_node_t node, next;
for ( node = link->head; node != NULL; ) {
for(node = link->head; node != NULL;) {
next = node->next;
FRISO_FREE( node );
FRISO_FREE(node);
node = next;
}
FRISO_FREE( link );
FRISO_FREE(link);
}
//clear all nodes in the link list.
FRISO_API friso_link_t link_list_clear(
friso_link_t link )
{
FRISO_API friso_link_t link_list_clear(
friso_link_t link) {
link_node_t node, next;
//free all the middle nodes.
for ( node = link->head->next; node != link->tail; )
{
for(node = link->head->next; node != link->tail;) {
next = node->next;
FRISO_FREE( node );
FRISO_FREE(node);
node = next;
}
@ -94,22 +89,20 @@ FRISO_API friso_link_t link_list_clear(
* find the node at a specified position.
* static
*/
__STATIC_API__ link_node_t get_node(
friso_link_t link, uint_t idx )
{
__STATIC_API__ link_node_t get_node(
friso_link_t link, uint_t idx) {
link_node_t p = NULL;
register uint_t t;
if ( idx >= 0 && idx < link->size )
{
if ( idx < link->size / 2 ) { //find from the head.
if(idx >= 0 && idx < link->size) {
if(idx < link->size / 2) { //find from the head.
p = link->head;
for ( t = 0; t <= idx; t++ )
p = p->next;
for(t = 0; t <= idx; t++)
p = p->next;
} else { //find from the tail.
p = link->tail;
for ( t = link->size; t > idx; t-- )
p = p->prev;
for(t = link->size; t > idx; t--)
p = p->prev;
}
}
@ -120,10 +113,10 @@ __STATIC_API__ link_node_t get_node(
* insert a node before the given node.
* static
*/
//__STATIC_API__ void insert_before(
// friso_link_t link,
// link_node_t node,
// void * value )
//__STATIC_API__ void insert_before(
// friso_link_t link,
// link_node_t node,
// void * value )
//{
// link_node_t e = new_node_entry( value, node->prev, node );
// e->prev->next = e;
@ -147,48 +140,44 @@ __STATIC_API__ link_node_t get_node(
*
* @return the value of the removed node.
*/
__STATIC_API__ void * remove_node(
friso_link_t link, link_node_t node )
{
__STATIC_API__ void * remove_node(
friso_link_t link, link_node_t node) {
void * _value = node->value;
node->prev->next = node->next;
node->next->prev = node->prev;
link->size--;
FRISO_FREE( node );
FRISO_FREE(node);
return _value;
}
//add a new node to the link list.(insert just before the tail)
FRISO_API void link_list_add(
friso_link_t link, void * value )
{
insert_before( link, link->tail, value );
FRISO_API void link_list_add(
friso_link_t link, void * value) {
insert_before(link, link->tail, value);
}
//add a new node before the given index.
FRISO_API void link_list_insert_before(
friso_link_t link, uint_t idx, void * value )
{
link_node_t node = get_node( link, idx );
if ( node != NULL ) {
insert_before( link, node, value );
FRISO_API void link_list_insert_before(
friso_link_t link, uint_t idx, void * value) {
link_node_t node = get_node(link, idx);
if(node != NULL) {
insert_before(link, node, value);
}
}
/*
* get the value with the specified node.
*
*
* @return the value of the node.
*/
FRISO_API void * link_list_get(
friso_link_t link, uint_t idx )
{
link_node_t node = get_node( link, idx );
if ( node != NULL ) {
FRISO_API void * link_list_get(
friso_link_t link, uint_t idx) {
link_node_t node = get_node(link, idx);
if(node != NULL) {
return node->value;
}
return NULL;
@ -198,17 +187,16 @@ FRISO_API void * link_list_get(
* set the value of the node that located in the specified position.
* we did't free the allocation of the old value, we return it to you.
* free it yourself when it is necessary.
*
*
* @return the old value.
*/
FRISO_API void *link_list_set(
friso_link_t link,
uint_t idx, void * value )
{
link_node_t node = get_node( link, idx );
FRISO_API void *link_list_set(
friso_link_t link,
uint_t idx, void * value) {
link_node_t node = get_node(link, idx);
void * _value = NULL;
if ( node != NULL ) {
if(node != NULL) {
_value = node->value;
node->value = value;
}
@ -222,14 +210,13 @@ FRISO_API void *link_list_set(
* @see remove_node
* @return the value of the node removed.
*/
FRISO_API void *link_list_remove(
friso_link_t link, uint_t idx )
{
link_node_t node = get_node( link, idx );
FRISO_API void *link_list_remove(
friso_link_t link, uint_t idx) {
link_node_t node = get_node(link, idx);
if ( node != NULL ) {
if(node != NULL) {
//printf("idx=%d, node->value=%s\n", idx, (string) node->value );
return remove_node( link, node );
return remove_node(link, node);
}
return NULL;
@ -237,48 +224,43 @@ FRISO_API void *link_list_remove(
/*
* remove the given node from the given link list.
*
*
* @see remove_node.
* @return the value of the node removed.
*/
FRISO_API void *link_list_remove_node(
friso_link_t link,
link_node_t node )
{
return remove_node( link, node );
FRISO_API void *link_list_remove_node(
friso_link_t link,
link_node_t node) {
return remove_node(link, node);
}
//remove the first node after the head
FRISO_API void *link_list_remove_first(
friso_link_t link )
{
if ( link->size > 0 ) {
return remove_node( link, link->head->next );
FRISO_API void *link_list_remove_first(
friso_link_t link) {
if(link->size > 0) {
return remove_node(link, link->head->next);
}
return NULL;
}
//remove the last node just before the tail.
FRISO_API void *link_list_remove_last(
friso_link_t link )
{
if ( link->size > 0 ) {
return remove_node( link, link->tail->prev );
FRISO_API void *link_list_remove_last(
friso_link_t link) {
if(link->size > 0) {
return remove_node(link, link->tail->prev);
}
return NULL;
}
//append a node from the tail.
FRISO_API void link_list_add_last(
friso_link_t link,
void *value )
{
insert_before( link, link->tail, value );
FRISO_API void link_list_add_last(
friso_link_t link,
void *value) {
insert_before(link, link->tail, value);
}
//append a note just after the head.
FRISO_API void link_list_add_first(
friso_link_t link, void *value )
{
insert_before( link, link->head->next, value );
FRISO_API void link_list_add_first(
friso_link_t link, void *value) {
insert_before(link, link->head->next, value);
}

View File

@ -1,6 +1,6 @@
/*
* utf-8 handle functions implementation.
*
*
* @author lionsoul<chenxin619315@gmail.com>
*/
@ -21,32 +21,30 @@
*
* @date: 2014-10-16
*/
__STATIC_API__ fstring create_buffer( uint_t length )
{
fstring buffer = ( fstring ) FRISO_MALLOC( length + 1 );
if ( buffer == NULL ) {
__STATIC_API__ fstring create_buffer(uint_t length) {
fstring buffer = (fstring) FRISO_MALLOC(length + 1);
if(buffer == NULL) {
___ALLOCATION_ERROR___
}
memset( buffer, 0x00, length + 1 );
memset(buffer, 0x00, length + 1);
return buffer;
}
//the __allocs should not be smaller than sb->length
__STATIC_API__ string_buffer_t resize_buffer(
string_buffer_t sb, uint_t __allocs )
{
__STATIC_API__ string_buffer_t resize_buffer(
string_buffer_t sb, uint_t __allocs) {
//create a new buffer.
//if ( __allocs < sb->length ) __allocs = sb->length + 1;
fstring str = create_buffer( __allocs );
//if ( __allocs < sb->length ) __allocs = sb->length + 1;
fstring str = create_buffer(__allocs);
//register uint_t t;
//for ( t = 0; t < sb->length; t++ ) {
// str[t] = sb->buffer[t];
//}
memcpy( str, sb->buffer, sb->length );
FRISO_FREE( sb->buffer );
memcpy(str, sb->buffer, sb->length);
FRISO_FREE(sb->buffer);
sb->buffer = str;
sb->allocs = __allocs;
@ -55,21 +53,20 @@ __STATIC_API__ string_buffer_t resize_buffer(
}
//create a new fstring buffer with a default opacity.
//FRISO_API string_buffer_t new_string_buffer( void )
//FRISO_API string_buffer_t new_string_buffer( void )
//{
// return new_string_buffer_with_opacity( __BUFFER_DEFAULT_LENGTH__ );
//}
//create a new fstring buffer with the given opacity.
FRISO_API string_buffer_t new_string_buffer_with_opacity( uint_t opacity )
{
string_buffer_t sb = ( string_buffer_t )
FRISO_MALLOC( sizeof( string_buffer_entry ) );
if ( sb == NULL ) {
FRISO_API string_buffer_t new_string_buffer_with_opacity(uint_t opacity) {
string_buffer_t sb = (string_buffer_t)
FRISO_MALLOC(sizeof(string_buffer_entry));
if(sb == NULL) {
___ALLOCATION_ERROR___
}
}
sb->buffer = create_buffer( opacity );
sb->buffer = create_buffer(opacity);
sb->length = 0;
sb->allocs = opacity;
@ -77,18 +74,17 @@ FRISO_API string_buffer_t new_string_buffer_with_opacity( uint_t opacity )
}
//create a buffer with the given string.
FRISO_API string_buffer_t new_string_buffer_with_string( fstring str )
{
FRISO_API string_buffer_t new_string_buffer_with_string(fstring str) {
//buffer allocations.
string_buffer_t sb = ( string_buffer_t )
FRISO_MALLOC( sizeof( string_buffer_entry ) );
if ( sb == NULL ) {
string_buffer_t sb = (string_buffer_t)
FRISO_MALLOC(sizeof(string_buffer_entry));
if(sb == NULL) {
___ALLOCATION_ERROR___
}
//initialize
sb->length = strlen( str );
sb->buffer = create_buffer( sb->length + __BUFFER_DEFAULT_LENGTH__ );
sb->length = strlen(str);
sb->buffer = create_buffer(sb->length + __BUFFER_DEFAULT_LENGTH__);
sb->allocs = sb->length + __BUFFER_DEFAULT_LENGTH__;
//register uint_t t;
@ -96,19 +92,18 @@ FRISO_API string_buffer_t new_string_buffer_with_string( fstring str )
//for ( t = 0; t < sb->length; t++ ) {
// sb->buffer[t] = str[t];
//}
memcpy( sb->buffer, str, sb->length );
memcpy(sb->buffer, str, sb->length);
return sb;
}
FRISO_API void string_buffer_append(
string_buffer_t sb, fstring __str )
{
register uint_t __len__ = strlen( __str );
FRISO_API void string_buffer_append(
string_buffer_t sb, fstring __str) {
register uint_t __len__ = strlen(__str);
//check the necessity to resize the buffer.
if ( sb->length + __len__ > sb->allocs ) {
sb = resize_buffer( sb, ( sb->length + __len__ ) * 2 + 1 );
if(sb->length + __len__ > sb->allocs) {
sb = resize_buffer(sb, (sb->length + __len__) * 2 + 1);
}
//register uint_t t;
@ -116,26 +111,24 @@ FRISO_API void string_buffer_append(
//for ( t = 0; t < __len__; t++ ) {
// sb->buffer[ sb->length++ ] = __str[t];
//}
memcpy( sb->buffer + sb->length, __str, __len__ );
memcpy(sb->buffer + sb->length, __str, __len__);
sb->length += __len__;
}
FRISO_API void string_buffer_append_char(
string_buffer_t sb, char ch )
{
FRISO_API void string_buffer_append_char(
string_buffer_t sb, char ch) {
//check the necessity to resize the buffer.
if ( sb->length + 1 > sb->allocs ) {
sb = resize_buffer( sb, sb->length * 2 + 1 );
if(sb->length + 1 > sb->allocs) {
sb = resize_buffer(sb, sb->length * 2 + 1);
}
sb->buffer[sb->length++] = ch;
}
FRISO_API void string_buffer_insert(
string_buffer_t sb,
uint_t idx,
fstring __str )
{
FRISO_API void string_buffer_insert(
string_buffer_t sb,
uint_t idx,
fstring __str) {
}
/*
@ -144,26 +137,25 @@ FRISO_API void string_buffer_insert(
*
* @return the new string.
*/
FRISO_API fstring string_buffer_remove(
string_buffer_t sb,
uint_t idx,
uint_t length )
{
FRISO_API fstring string_buffer_remove(
string_buffer_t sb,
uint_t idx,
uint_t length) {
uint_t t;
//move the bytes after the idx + length
for ( t = idx + length; t < sb->length; t++ ) {
for(t = idx + length; t < sb->length; t++) {
sb->buffer[t - length] = sb->buffer[t];
}
sb->buffer[t] = '\0';
//memcpy( sb->buffer + idx,
// sb->buffer + idx + length,
//memcpy( sb->buffer + idx,
// sb->buffer + idx + length,
// sb->length - idx - length );
t = sb->length - idx;
if ( t > 0 ) {
sb->length -= ( t > length ) ? length : t;
if(t > 0) {
sb->length -= (t > length) ? length : t;
}
sb->buffer[sb->length-1] = '\0';
sb->buffer[sb->length - 1] = '\0';
return sb->buffer;
}
@ -172,25 +164,23 @@ FRISO_API fstring string_buffer_remove(
* turn the string_buffer to a string.
* or return the buffer of the string_buffer.
*/
FRISO_API string_buffer_t string_buffer_trim( string_buffer_t sb )
{
FRISO_API string_buffer_t string_buffer_trim(string_buffer_t sb) {
//resize the buffer.
if ( sb->length < sb->allocs - 1 ) {
sb = resize_buffer( sb, sb->length + 1 );
if(sb->length < sb->allocs - 1) {
sb = resize_buffer(sb, sb->length + 1);
}
return sb;
}
/*
* free the given fstring buffer.
* and this function will not free the allocations of the
* and this function will not free the allocations of the
* string_buffer_t->buffer, we return it to you, if there is
* a necessary you could free it youself by calling free();
*/
FRISO_API fstring string_buffer_devote( string_buffer_t sb )
{
FRISO_API fstring string_buffer_devote(string_buffer_t sb) {
fstring buffer = sb->buffer;
FRISO_FREE( sb );
FRISO_FREE(sb);
return buffer;
}
@ -198,17 +188,15 @@ FRISO_API fstring string_buffer_devote( string_buffer_t sb )
* clear the given fstring buffer.
* reset its buffer with 0 and reset its length to 0.
*/
FRISO_API void string_buffer_clear( string_buffer_t sb )
{
memset( sb->buffer, 0x00, sb->length );
FRISO_API void string_buffer_clear(string_buffer_t sb) {
memset(sb->buffer, 0x00, sb->length);
sb->length = 0;
}
//free everything of the fstring buffer.
FRISO_API void free_string_buffer( string_buffer_t sb )
{
FRISO_FREE( sb->buffer );
FRISO_FREE( sb );
FRISO_API void free_string_buffer(string_buffer_t sb) {
FRISO_FREE(sb->buffer);
FRISO_FREE(sb);
}
@ -216,15 +204,14 @@ FRISO_API void free_string_buffer( string_buffer_t sb )
* create a new string_split_entry.
*
* @param source
* @return string_split_t;
* @return string_split_t;
*/
FRISO_API string_split_t new_string_split(
fstring delimiter,
fstring source )
{
string_split_t e = ( string_split_t )
FRISO_MALLOC( sizeof( string_split_entry ) );
if ( e == NULL ) {
FRISO_API string_split_t new_string_split(
fstring delimiter,
fstring source) {
string_split_t e = (string_split_t)
FRISO_MALLOC(sizeof(string_split_entry));
if(e == NULL) {
___ALLOCATION_ERROR___;
}
@ -237,70 +224,65 @@ FRISO_API string_split_t new_string_split(
return e;
}
FRISO_API void string_split_reset(
string_split_t sst,
fstring delimiter,
fstring source )
{
FRISO_API void string_split_reset(
string_split_t sst,
fstring delimiter,
fstring source) {
sst->delimiter = delimiter;
sst->delLen = strlen(delimiter);
sst->source = source;
sst->srcLen = strlen(source);
sst->idx = 0;
}
FRISO_API void string_split_set_source(
string_split_t sst, fstring source )
{
sst->source = source;
sst->srcLen = strlen(source);
sst->idx = 0;
}
FRISO_API void string_split_set_delimiter(
string_split_t sst, fstring delimiter )
{
sst->delimiter = delimiter;
sst->delLen = strlen( delimiter );
FRISO_API void string_split_set_source(
string_split_t sst, fstring source) {
sst->source = source;
sst->srcLen = strlen(source);
sst->idx = 0;
}
FRISO_API void free_string_split( string_split_t sst )
{
FRISO_API void string_split_set_delimiter(
string_split_t sst, fstring delimiter) {
sst->delimiter = delimiter;
sst->delLen = strlen(delimiter);
sst->idx = 0;
}
FRISO_API void free_string_split(string_split_t sst) {
FRISO_FREE(sst);
}
/**
* get the next split fstring, and copy the
* splited fstring into the __dst buffer .
* get the next split fstring, and copy the
* splited fstring into the __dst buffer .
*
* @param string_split_t
* @param __dst
* @return fstring (NULL if reach the end of the source
* @return fstring (NULL if reach the end of the source
* or there is no more segmentation)
*/
FRISO_API fstring string_split_next(
string_split_t sst, fstring __dst)
{
FRISO_API fstring string_split_next(
string_split_t sst, fstring __dst) {
uint_t i, _ok;
fstring _dst = __dst;
//check if reach the end of the fstring
if ( sst->idx >= sst->srcLen ) return NULL;
if(sst->idx >= sst->srcLen) return NULL;
while ( 1 ) {
while(1) {
_ok = 1;
for ( i = 0; i < sst->delLen
&& (sst->idx + i < sst->srcLen); i++ ) {
if ( sst->source[sst->idx+i] != sst->delimiter[i] ) {
for(i = 0; i < sst->delLen
&& (sst->idx + i < sst->srcLen); i++) {
if(sst->source[sst->idx + i] != sst->delimiter[i]) {
_ok = 0;
break;
}
}
}
//find the delimiter here,
//break the loop and self plus the sst->idx, then return the buffer .
if ( _ok == 1 ) {
//break the loop and self plus the sst->idx, then return the buffer .
if(_ok == 1) {
sst->idx += sst->delLen;
break;
}
@ -308,7 +290,7 @@ FRISO_API fstring string_split_next(
//coy the char to the buffer
*_dst++ = sst->source[sst->idx++];
//check if reach the end of the fstring
if ( sst->idx >= sst->srcLen ) break;
if(sst->idx >= sst->srcLen) break;
}
*_dst = '\0';

View File

@ -8,10 +8,10 @@
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char **args ) {
int main(int argc, char **args) {
//create a new array list.
friso_array_t array = new_array_list();
friso_array_t array = new_array_list();
fstring keys[] = {
"chenmanwen", "yangqinghua",
"chenxin", "luojiangyan", "xiaoyanzi", "bibi",
@ -20,31 +20,31 @@ int main( int argc, char **args ) {
"chenpei", "liheng", "zhangzhigang", "zhgangyishao", "yangjiangbo",
"caizaili", "panpan", "xiaolude", "yintanwen"
};
int j, idx = 2, len = sizeof( keys ) / sizeof( fstring );
int j, idx = 2, len = sizeof(keys) / sizeof(fstring);
for ( j = 0; j < len; j++ ) {
array_list_add( array, keys[j] );
for(j = 0; j < len; j++) {
array_list_add(array, keys[j]);
}
printf("length=%d, allocations=%d\n", array->length, array->allocs );
array_list_trim( array );
printf("after tirm length=%d, allocations=%d\n", array->length, array->allocs );
printf("idx=%d, value=%s\n", idx, ( fstring ) array_list_get( array, idx ) );
printf("length=%d, allocations=%d\n", array->length, array->allocs);
array_list_trim(array);
printf("after tirm length=%d, allocations=%d\n", array->length, array->allocs);
printf("idx=%d, value=%s\n", idx, (fstring) array_list_get(array, idx));
printf("\nAfter set %dth item.\n", idx );
array_list_set( array, idx, "chenxin__" );
printf("idx=%d, value=%s\n", idx, ( fstring ) array_list_get( array, idx ) );
printf("\nAfter set %dth item.\n", idx);
array_list_set(array, idx, "chenxin__");
printf("idx=%d, value=%s\n", idx, (fstring) array_list_get(array, idx));
printf("\nAfter remove %dth item.\n", idx );
array_list_remove( array, idx );
printf("length=%d, allocations=%d\n", array->length, array->allocs );
printf("idx=%d, value=%s\n", idx, ( fstring ) array_list_get( array, idx ) );
printf("\nAfter remove %dth item.\n", idx);
array_list_remove(array, idx);
printf("length=%d, allocations=%d\n", array->length, array->allocs);
printf("idx=%d, value=%s\n", idx, (fstring) array_list_get(array, idx));
printf("\nInsert a item at %dth\n", idx );
array_list_insert( array, idx, "*chenxin*" );
printf("idx=%d, value=%s\n", idx, ( fstring ) array_list_get( array, idx ) );
printf("\nInsert a item at %dth\n", idx);
array_list_insert(array, idx, "*chenxin*");
printf("idx=%d, value=%s\n", idx, (fstring) array_list_get(array, idx));
free_array_list( array );
free_array_list(array);
return 0;
}

View File

@ -32,19 +32,18 @@ break;
println("+---------------------------------------------------------------+");
//read a line from a command line.
static fstring getLine( FILE *fp, fstring __dst )
{
static fstring getLine(FILE *fp, fstring __dst) {
register int c;
register fstring cs;
cs = __dst;
while ( ( c = getc( fp ) ) != EOF ) {
if ( c == '\n' ) break;
*cs++ = c;
while((c = getc(fp)) != EOF) {
if(c == '\n') break;
*cs++ = c;
}
*cs = '\0';
return ( c == EOF && cs == __dst ) ? NULL : __dst;
return (c == EOF && cs == __dst) ? NULL : __dst;
}
/*static void printcode( fstring str ) {
@ -57,8 +56,7 @@ static fstring getLine( FILE *fp, fstring __dst )
putchar('\n');
}*/
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
clock_t s_time, e_time;
char line[__INPUT_LENGTH__] = {0};
@ -70,13 +68,13 @@ int main(int argc, char **argv)
friso_task_t task;
// get the lexicon directory from command line arguments
for ( i = 0; i < argc; i++ ) {
if ( strcasecmp( "-init", argv[i] ) == 0 ) {
__path__ = argv[i+1];
for(i = 0; i < argc; i++) {
if(strcasecmp("-init", argv[i]) == 0) {
__path__ = argv[i + 1];
}
}
if ( __path__ == NULL ) {
if(__path__ == NULL) {
println("Usage: friso -init lexicon path");
exit(0);
}
@ -90,12 +88,12 @@ int main(int argc, char **argv)
friso_dic_load_from_ifile( dic, __path__, __LENGTH__ );
friso_set_dic( friso, dic );
friso_set_mode( friso, __FRISO_COMPLEX_MODE__ );*/
if ( friso_init_from_ifile(friso, config, __path__) != 1 ) {
if(friso_init_from_ifile(friso, config, __path__) != 1) {
printf("fail to initialize friso and config.\n");
goto err;
}
switch ( config->mode ) {
switch(config->mode) {
case __FRISO_SIMPLE_MODE__:
mode = "Simple";
break;
@ -114,41 +112,41 @@ int main(int argc, char **argv)
e_time = clock();
printf("Initialized in %fsec\n", (double) ( e_time - s_time ) / CLOCKS_PER_SEC );
printf("Initialized in %fsec\n", (double)(e_time - s_time) / CLOCKS_PER_SEC);
printf("Mode: %s\n", mode);
printf("+-Version: %s (%s)\n", friso_version(), friso->charset == FRISO_UTF8 ? "UTF-8" : "GBK" );
printf("+-Version: %s (%s)\n", friso_version(), friso->charset == FRISO_UTF8 ? "UTF-8" : "GBK");
___ABOUT___;
//set the task.
task = friso_new_task();
while ( 1 ) {
while(1) {
print("friso>> ");
getLine( stdin, line );
getLine(stdin, line);
//exit the programe
if (strcasecmp( line, "quit") == 0) {
if(strcasecmp(line, "quit") == 0) {
___EXIT_INFO___
}
//for ( i = 0; i < 1000000; i++ ) {
//set the task text.
friso_set_text( task, line );
friso_set_text(task, line);
println("分词结果:");
s_time = clock();
while ( ( config->next_token( friso, config, task ) ) != NULL ) {
while((config->next_token(friso, config, task)) != NULL) {
printf(
"%s[%d, %d, %d] ",
task->token->word,
task->token->offset,
task->token->length,
"%s[%d, %d, %d] ",
task->token->word,
task->token->offset,
task->token->length,
task->token->rlen
);
// printf("%s ", task->token->word);
}
//}
e_time = clock();
printf("\nDone, cost < %fsec\n", ( (double)(e_time - s_time) ) / CLOCKS_PER_SEC );
printf("\nDone, cost < %fsec\n", ((double)(e_time - s_time)) / CLOCKS_PER_SEC);
}

View File

@ -1,19 +1,18 @@
/**
* hashmap testing program
*
*
* @author lionsoul<chenxin619315@gmail.com>
*/
#include "friso_API.h"
#include <stdio.h>
void print_hash_info( friso_hash_t _hash ) {
void print_hash_info(friso_hash_t _hash) {
printf("info:length=%d, size=%d, facotr=%f, threshold=%d\n", _hash->length, \
_hash->size, _hash->factor, _hash->threshold);
}
_hash->size, _hash->factor, _hash->threshold);
}
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
friso_hash_t _hash = new_hash_table();
char *names[] = {
"陈满文", "阳清华",
@ -31,13 +30,13 @@ int main(int argc, char **argv)
"周安", "郭桥安",
"刘敏", "黄广华",
"李胜", "黄海清"
};
};
//char *str[] = {"陈鑫", "张仁芳", "比比"};
char **str = names;
int j, len = 30;
print_hash_info( _hash );
for (j = 0; j < len; j++) {
print_hash_info(_hash);
for(j = 0; j < len; j++) {
hash_put_mapping(_hash, names[j], names[j]);
}
@ -47,7 +46,7 @@ int main(int argc, char **argv)
getchar();
//remove mappings
for (j = 0; j < len; j++) {
for(j = 0; j < len; j++) {
printf("Exist %s?%2d\n", str[j], hash_exist_mapping(_hash, str[j]));
printf("Now, remove %s\n", str[j]);
hash_remove_mapping(_hash, str[j]);

View File

@ -1,6 +1,6 @@
/*
* lex functions test program.
*
*
* @author lionsoul<chenxin619315@gmail.com>
*/
@ -16,8 +16,7 @@
printf("3. other search the words in the dictionary.\n"); \
printf("4. quit exit the programe.\n");
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
lex_entry_t e;
int lex = __LEX_CJK_WORDS__;
char _line[__LENGTH__];
@ -59,42 +58,42 @@ int main(int argc, char **argv)
//__CN_DNAME2__
friso_dic_load(friso, config, __LEX_CN_DNAME2__, "../vendors/dict/UTF-8/lex-dname-2.lex", __LENGTH__);
//__CN_LNA__
friso_dic_load(friso, config, __LEX_CN_LNA__, "../vendors/dict/UTF-8/lex-ln-adorn.lex", __LENGTH__ );
friso_dic_load(friso, config, __LEX_CN_LNA__, "../vendors/dict/UTF-8/lex-ln-adorn.lex", __LENGTH__);
e_time = clock();
printf(
"Done, cost: %f sec, size=%d\n",
(double) (e_time - s_time) / CLOCKS_PER_SEC,
"Done, cost: %f sec, size=%d\n",
(double)(e_time - s_time) / CLOCKS_PER_SEC,
friso_all_dic_size(friso->dic)
);
while (1) {
while(1) {
printf("friso-%d>> ", lex);
if (scanf("%s", _line) != 1) {
if(scanf("%s", _line) != 1) {
printf("Invalid input\n");
continue;
}
if (strcmp( _line, "quit" ) == 0) {
if(strcmp(_line, "quit") == 0) {
break;
} else if ( strcmp(_line, "help") == 0 ) {
} else if(strcmp(_line, "help") == 0) {
___PRINT_HELP_INFO___
} else if ( strcmp( _line, "#set" ) == 0 ) {
} else if(strcmp(_line, "#set") == 0) {
printf("lex_t>> ");
if (scanf("%d", &lex) != 1) {
if(scanf("%d", &lex) != 1) {
printf("Warning: Invalid lex type input\n");
continue;
}
} else {
s_time = clock();
e = friso_dic_get( friso->dic, lex, _line );
e = friso_dic_get(friso->dic, lex, _line);
e_time = clock();
if (e != NULL) {
if(e != NULL) {
printf(
"word=%s, syn=%s, fre=%d, cost:%fsec\n",
e->word, e->syn==NULL? "NULL" : (char *)e->syn->items[0],
e->fre,
(double) (e_time - s_time) / CLOCKS_PER_SEC
"word=%s, syn=%s, fre=%d, cost:%fsec\n",
e->word, e->syn == NULL ? "NULL" : (char *)e->syn->items[0],
e->fre,
(double)(e_time - s_time) / CLOCKS_PER_SEC
);
} else {
printf("%s was not found.\n", _line);

View File

@ -1,6 +1,6 @@
/*
* link list test programe.
*
*
* @author lionsoul<chenxin619315@gmail.com>
*/
@ -8,7 +8,7 @@
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char **args ) {
int main(int argc, char **args) {
friso_link_t link;
fstring keys[] = {
@ -19,32 +19,32 @@ int main( int argc, char **args ) {
"chenpei", "liheng", "zhangzhigang", "zhgangyishao", "yangjiangbo",
"caizaili", "panpan", "xiaolude", "yintanwen"
};
int j, len = sizeof( keys ) / sizeof( fstring );
int j, len = sizeof(keys) / sizeof(fstring);
link = new_link_list();
//print the size of the link
printf("size=%d\n", link->size );
printf("size=%d\n", link->size);
for ( j = 0; j < len; j++ ) {
for(j = 0; j < len; j++) {
//link_add( link, keys[j] );
link_list_add_last( link, keys[j] );
link_list_add_last(link, keys[j]);
}
printf("size=%d\n", link->size );
printf("size=%d\n", link->size);
for ( j = 0; j < len / 2; j++ ) {
for(j = 0; j < len / 2; j++) {
//printf("idx=%d, remove %s\n", j, ( fstring ) link_remove( link, 0 ) );
printf("idx=%d, remove %s\n", j, ( fstring ) link_list_remove_first( link ) );
printf("idx=%d, remove %s\n", j, (fstring) link_list_remove_first(link));
}
printf("size=%d\n", link->size );
printf("size=%d\n", link->size);
//clear all the nodes
link_list_clear( link );
printf("size=%d, head->next->value=%s\n", link->size, ( fstring ) link->head->next->value );
link_list_clear(link);
printf("size=%d, head->next->value=%s\n", link->size, (fstring) link->head->next->value);
free_link_list( link );
free_link_list(link);
return 0;
}

View File

@ -8,17 +8,16 @@
#include <stdio.h>
#include <stdlib.h>
int main ( int argc, char **args )
{
fstring source = ",I am a chinese,,my name is Lion,and i am the author of friso,bug report email chenxin619315@gmail.com,qq:1187582057";
int main(int argc, char **args) {
fstring source = ",I am a chinese,,my name is Lion,and i am the author of friso,bug report email chenxin619315@gmail.com,qq:1187582057";
char buffer[128];
string_split_t split = new_string_split(",", source );
string_split_t split = new_string_split(",", source);
printf("sst->idx=%d\n", split->idx);
printf("sst->srcLen=%d\n", split->srcLen);
printf("sst->delLen=%d\n", split->delLen);
while ( string_split_next(split, buffer) != NULL) {
while(string_split_next(split, buffer) != NULL) {
printf("buffer:%s\n", buffer);
}

View File

@ -9,39 +9,39 @@
#include <stdlib.h>
#include <string.h>
int main( int argc, char **args ) {
int main(int argc, char **args) {
fstring str = "康熙字典部首, 符号和标点, 统一表意符号扩展 A ,CJK㈩兼Ⅱ容形式⑩.";
char word[4];
int bytes, t, j, length = strlen( str );
int bytes, t, j, length = strlen(str);
string_buffer_t sb = new_string_buffer();
printf("str=%s, length=%d\n", str, length );
printf("str=%s, length=%d\n", str, length);
for (t = 0; t < length; t += bytes) {
for(t = 0; t < length; t += bytes) {
bytes = get_utf8_bytes(*(str + t));
if ( bytes == 0 ) {
if(bytes == 0) {
continue;
}
for ( j = 0; j < bytes; j++ ) {
word[j] = *(str + t + j );
for(j = 0; j < bytes; j++) {
word[j] = *(str + t + j);
}
word[j] = '\0';
string_buffer_append( sb, word );
printf("word=%s\n", word );
string_buffer_append(sb, word);
printf("word=%s\n", word);
}
printf("length=%d, buffer=%s\n", sb->length, sb->buffer );
string_buffer_remove( sb, 0, 3 );
printf("length=%d, buffer=%s\n", sb->length, sb->buffer );
string_buffer_remove( sb, 0, 3 );
printf("length=%d, buffer=%s\n", sb->length, sb->buffer );
string_buffer_remove( sb, sb->length - 3, 6 );
sb = string_buffer_trim( sb );
printf("length=%d, buffer=%s\n", sb->length, string_buffer_devote( sb ) );
printf("length=%d, buffer=%s\n", sb->length, sb->buffer);
string_buffer_remove(sb, 0, 3);
printf("length=%d, buffer=%s\n", sb->length, sb->buffer);
string_buffer_remove(sb, 0, 3);
printf("length=%d, buffer=%s\n", sb->length, sb->buffer);
string_buffer_remove(sb, sb->length - 3, 6);
sb = string_buffer_trim(sb);
printf("length=%d, buffer=%s\n", sb->length, string_buffer_devote(sb));
//00011110 - yuan ma
//11100001 - fa ma

View File

@ -23,9 +23,8 @@
static AppMatch *app_match_Class = nullptr;
AppMatch *AppMatch::getAppMatch()
{
if (!app_match_Class) {
AppMatch *AppMatch::getAppMatch() {
if(!app_match_Class) {
app_match_Class = new AppMatch;
}
return app_match_Class;
@ -33,141 +32,130 @@ AppMatch *AppMatch::getAppMatch()
AppMatch::AppMatch(QObject *parent) : QThread(parent)
// m_versionCommand(new QProcess(this))
{
m_watchAppDir=new QFileSystemWatcher(this);
m_watchAppDir = new QFileSystemWatcher(this);
m_watchAppDir->addPath("/usr/share/applications/");
QDir androidPath(QDir::homePath()+"/.local/share/applications/");
if(androidPath.exists()){
m_watchAppDir->addPath(QDir::homePath()+"/.local/share/applications/");
QDir androidPath(QDir::homePath() + "/.local/share/applications/");
if(androidPath.exists()) {
m_watchAppDir->addPath(QDir::homePath() + "/.local/share/applications/");
}
qDBusRegisterMetaType<QMap<QString,QString>>();
qDBusRegisterMetaType<QList<QMap<QString,QString>>>();
m_interFace=new QDBusInterface ("com.kylin.softwarecenter.getsearchresults", "/com/kylin/softwarecenter/getsearchresults",
"com.kylin.getsearchresults",
QDBusConnection::sessionBus());
if (!m_interFace->isValid())
{
qDBusRegisterMetaType<QMap<QString, QString>>();
qDBusRegisterMetaType<QList<QMap<QString, QString>>>();
m_interFace = new QDBusInterface("com.kylin.softwarecenter.getsearchresults", "/com/kylin/softwarecenter/getsearchresults",
"com.kylin.getsearchresults",
QDBusConnection::sessionBus());
if(!m_interFace->isValid()) {
qWarning() << qPrintable(QDBusConnection::sessionBus().lastError().message());
}
qDebug()<<"AppMatch is new";
}
qDebug() << "AppMatch is new";
}
AppMatch::~AppMatch(){
if(m_interFace){
AppMatch::~AppMatch() {
if(m_interFace) {
delete m_interFace;
}
m_interFace=NULL;
if(m_watchAppDir){
m_interFace = NULL;
if(m_watchAppDir) {
delete m_watchAppDir;
}
m_watchAppDir=NULL;
m_watchAppDir = NULL;
}
void AppMatch::startMatchApp(QString input,QMap<NameString,QStringList> &installed,QMap<NameString,QStringList> &softwarereturn){
m_sourceText=input;
void AppMatch::startMatchApp(QString input, QMap<NameString, QStringList> &installed, QMap<NameString, QStringList> &softwarereturn) {
m_sourceText = input;
getAppName(installed);
softWareCenterSearch(softwarereturn);
qDebug()<<"match app is successful!";
qDebug() << "match app is successful!";
}
/**
* @brief AppMatch::getAllDesktopFilePath desktop文件
* @param path desktop文件夹
*/
void AppMatch::getAllDesktopFilePath(QString path){
void AppMatch::getAllDesktopFilePath(QString path) {
char* name;
char* icon;
QStringList applist;
GKeyFileFlags flags=G_KEY_FILE_NONE;
GKeyFile* keyfile=g_key_file_new ();
GKeyFileFlags flags = G_KEY_FILE_NONE;
GKeyFile* keyfile = g_key_file_new();
QDir dir(path);
if (!dir.exists()) {
if(!dir.exists()) {
return;
}
dir.setFilter(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot);
dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
dir.setSorting(QDir::DirsFirst);
QFileInfoList list = dir.entryInfoList();
list.removeAll(QFileInfo("/usr/share/applications/screensavers"));
if(list.size()< 1 ) {
if(list.size() < 1) {
return;
}
int i=0;
int i = 0;
//递归算法的核心部分
do{
do {
QFileInfo fileInfo = list.at(i);
//如果是文件夹,递归
bool isDir = fileInfo.isDir();
if(isDir) {
getAllDesktopFilePath(fileInfo.filePath());
}
else{
} else {
//过滤LXQt、KDE
QString filePathStr=fileInfo.filePath();
if(filePathStr.contains("KDE",Qt::CaseInsensitive)||
QString filePathStr = fileInfo.filePath();
if(filePathStr.contains("KDE", Qt::CaseInsensitive) ||
// filePathStr.contains("mate",Qt::CaseInsensitive)||
filePathStr.contains("LX",Qt::CaseInsensitive) ){
filePathStr.contains("LX", Qt::CaseInsensitive)) {
i++;
continue;
}
//过滤后缀不是.desktop的文件
if(!filePathStr.endsWith(".desktop"))
{
if(!filePathStr.endsWith(".desktop")) {
i++;
continue;
}
QByteArray fpbyte=filePathStr.toLocal8Bit();
char* filepath=fpbyte.data();
g_key_file_load_from_file(keyfile,filepath,flags,nullptr);
char* ret_1=g_key_file_get_locale_string(keyfile,"Desktop Entry","NoDisplay", nullptr, nullptr);
if(ret_1!=nullptr)
{
QString str=QString::fromLocal8Bit(ret_1);
if(str.contains("true"))
{
QByteArray fpbyte = filePathStr.toLocal8Bit();
char* filepath = fpbyte.data();
g_key_file_load_from_file(keyfile, filepath, flags, nullptr);
char* ret_1 = g_key_file_get_locale_string(keyfile, "Desktop Entry", "NoDisplay", nullptr, nullptr);
if(ret_1 != nullptr) {
QString str = QString::fromLocal8Bit(ret_1);
if(str.contains("true")) {
i++;
continue;
}
}
char* ret_2=g_key_file_get_locale_string(keyfile,"Desktop Entry","NotShowIn", nullptr, nullptr);
if(ret_2!=nullptr)
{
QString str=QString::fromLocal8Bit(ret_2);
if(str.contains("UKUI"))
{
char* ret_2 = g_key_file_get_locale_string(keyfile, "Desktop Entry", "NotShowIn", nullptr, nullptr);
if(ret_2 != nullptr) {
QString str = QString::fromLocal8Bit(ret_2);
if(str.contains("UKUI")) {
i++;
continue;
}
}
//过滤中英文名为空的情况
QLocale cn;
QString language=cn.languageToString(cn.language());
if(QString::compare(language,"Chinese")==0)
{
char* nameCh=g_key_file_get_string(keyfile,"Desktop Entry","Name[zh_CN]", nullptr);
char* nameEn=g_key_file_get_string(keyfile,"Desktop Entry","Name", nullptr);
if(QString::fromLocal8Bit(nameCh).isEmpty() && QString::fromLocal8Bit(nameEn).isEmpty())
{
QString language = cn.languageToString(cn.language());
if(QString::compare(language, "Chinese") == 0) {
char* nameCh = g_key_file_get_string(keyfile, "Desktop Entry", "Name[zh_CN]", nullptr);
char* nameEn = g_key_file_get_string(keyfile, "Desktop Entry", "Name", nullptr);
if(QString::fromLocal8Bit(nameCh).isEmpty() && QString::fromLocal8Bit(nameEn).isEmpty()) {
i++;
continue;
}
} else {
char* name = g_key_file_get_string(keyfile, "Desktop Entry", "Name", nullptr);
if(QString::fromLocal8Bit(name).isEmpty()) {
i++;
continue;
}
}
else {
char* name=g_key_file_get_string(keyfile,"Desktop Entry","Name", nullptr);
if(QString::fromLocal8Bit(name).isEmpty())
{
i++;
continue;
}
}
name=g_key_file_get_locale_string(keyfile,"Desktop Entry","Name", nullptr, nullptr);
icon=g_key_file_get_locale_string(keyfile,"Desktop Entry","Icon", nullptr, nullptr);
if(!m_filePathList.contains(filePathStr)){
name = g_key_file_get_locale_string(keyfile, "Desktop Entry", "Name", nullptr, nullptr);
icon = g_key_file_get_locale_string(keyfile, "Desktop Entry", "Icon", nullptr, nullptr);
if(!m_filePathList.contains(filePathStr)) {
NameString appname;
appname.app_name = QString::fromLocal8Bit(name);
m_installAppMap.insert(appname,applist<<filePathStr<<QString::fromLocal8Bit(icon)<<""<<"");
applist.clear();
m_installAppMap.insert(appname, applist << filePathStr << QString::fromLocal8Bit(icon) << "" << "");
applist.clear();
}
// m_filePathList.append(filePathStr);
}
@ -181,8 +169,7 @@ void AppMatch::getAllDesktopFilePath(QString path){
* @brief AppMatch::getDesktopFilePath
*
*/
void AppMatch::getDesktopFilePath()
{
void AppMatch::getDesktopFilePath() {
m_filePathList.clear();
m_installAppMap.clear();
m_filePathList.append("/usr/share/applications/software-properties-livepatch.desktop");
@ -239,13 +226,12 @@ void AppMatch::getDesktopFilePath()
// }
}
void AppMatch::getAppName(QMap<NameString,QStringList> &installed)
{
void AppMatch::getAppName(QMap<NameString, QStringList> &installed) {
QMap<NameString, QStringList>::const_iterator i;
for(i=m_installAppMap.constBegin();i!=m_installAppMap.constEnd();++i){
appNameMatch(i.key().app_name,installed);
}
qDebug()<<"installed app match is successful!";
for(i = m_installAppMap.constBegin(); i != m_installAppMap.constEnd(); ++i) {
appNameMatch(i.key().app_name, installed);
}
qDebug() << "installed app match is successful!";
}
/**
@ -254,67 +240,63 @@ void AppMatch::getAppName(QMap<NameString,QStringList> &installed)
* @param appname
*
*/
void AppMatch::appNameMatch(QString appname,QMap<NameString,QStringList> &installed){
void AppMatch::appNameMatch(QString appname, QMap<NameString, QStringList> &installed) {
NameString name{appname};
QStringList list;
QStringList pinyinlist;
pinyinlist=FileUtils::findMultiToneWords(appname);
QMapIterator<NameString,QStringList> iter(m_installAppMap);
while(iter.hasNext())
{
pinyinlist = FileUtils::findMultiToneWords(appname);
QMapIterator<NameString, QStringList> iter(m_installAppMap);
while(iter.hasNext()) {
iter.next();
if (iter.key().app_name == appname) {
if(iter.key().app_name == appname) {
list = iter.value();
break;
}
}
if(appname.contains(m_sourceText,Qt::CaseInsensitive)){
if(appname.contains(m_sourceText, Qt::CaseInsensitive)) {
// installed.insert(name,m_installAppMap.value(name));
installed.insert(name,list);
installed.insert(name, list);
return;
}
for(int i = 0;i<pinyinlist.size()/2;i++){
QString shouzimu=pinyinlist.at(2*i+1);// 中文转首字母
if(shouzimu.contains(m_sourceText,Qt::CaseInsensitive)){
for(int i = 0; i < pinyinlist.size() / 2; i++) {
QString shouzimu = pinyinlist.at(2 * i + 1); // 中文转首字母
if(shouzimu.contains(m_sourceText, Qt::CaseInsensitive)) {
// installed.insert(name,m_installAppMap.value(name));
installed.insert(name,list);
installed.insert(name, list);
return;
}
if(m_sourceText.size()<2)
if(m_sourceText.size() < 2)
return;
QString pinyin=pinyinlist.at(2*i);// 中文转拼音
if(pinyin.contains(m_sourceText,Qt::CaseInsensitive)){
QString pinyin = pinyinlist.at(2 * i); // 中文转拼音
if(pinyin.contains(m_sourceText, Qt::CaseInsensitive)) {
// installed.insert(name,m_installAppMap.value(name));
installed.insert(name,list);
installed.insert(name, list);
return;
}
}
}
void AppMatch::softWareCenterSearch(QMap<NameString,QStringList> &softwarereturn){
if(m_interFace->timeout()!=-1){
qWarning()<<"softWareCente Dbus is timeout !";
void AppMatch::softWareCenterSearch(QMap<NameString, QStringList> &softwarereturn) {
if(m_interFace->timeout() != -1) {
qWarning() << "softWareCente Dbus is timeout !";
return;
}
slotDBusCallFinished(softwarereturn);
qDebug()<<"softWareCenter match app is successful!";
qDebug() << "softWareCenter match app is successful!";
}
void AppMatch::slotDBusCallFinished(QMap<NameString,QStringList> &softwarereturn){
QDBusReply<QList<QMap<QString,QString>>> reply = m_interFace->call("get_search_result",m_sourceText); //阻塞,直到远程方法调用完成。
void AppMatch::slotDBusCallFinished(QMap<NameString, QStringList> &softwarereturn) {
QDBusReply<QList<QMap<QString, QString>>> reply = m_interFace->call("get_search_result", m_sourceText); //阻塞,直到远程方法调用完成。
// QDBusPendingReply<QList<QMap<QString,QString>>> reply = *call;
if (reply.isValid())
{
parseSoftWareCenterReturn(reply.value(),softwarereturn);
}
else
{
qWarning() << "value method called failed!";
}
if(reply.isValid()) {
parseSoftWareCenterReturn(reply.value(), softwarereturn);
} else {
qWarning() << "value method called failed!";
}
// call->deleteLater();
}
void AppMatch::parseSoftWareCenterReturn(QList<QMap<QString,QString>> list,QMap<NameString,QStringList> &softwarereturn){
void AppMatch::parseSoftWareCenterReturn(QList<QMap<QString, QString>> list, QMap<NameString, QStringList> &softwarereturn) {
// qWarning()<<list;
QString appname;
NameString name;
@ -323,24 +305,24 @@ void AppMatch::parseSoftWareCenterReturn(QList<QMap<QString,QString>> list,QMap<
QStringList applist;
QLocale locale;
QString pkgname;
for(int i=0;i<list.size();i++){
for(int i = 0; i < list.size(); i++) {
// qWarning()<<list.at(i).keys();
if(locale.language()==QLocale::Chinese){
appname=list.at(i).value("displayname_cn");
pkgname = list.at(i).value("appname");
if(locale.language() == QLocale::Chinese) {
appname = list.at(i).value("displayname_cn");
pkgname = list.at(i).value("appname");
}
if(locale.language()==QLocale::English){
appname=list.at(i).value("appname");
if(locale.language() == QLocale::English) {
appname = list.at(i).value("appname");
}
appdiscription=list.at(i).value("discription");
appicon=list.at(i).value("icon");
appdiscription = list.at(i).value("discription");
appicon = list.at(i).value("icon");
name.app_name = appname;
pkgname.isEmpty() ? softwarereturn.insert(name,applist<<""<<appicon<<""<<appdiscription) : softwarereturn.insert(name,applist<<""<<appicon<<pkgname<<appdiscription);
pkgname.isEmpty() ? softwarereturn.insert(name, applist << "" << appicon << "" << appdiscription) : softwarereturn.insert(name, applist << "" << appicon << pkgname << appdiscription);
applist.clear();
}
}
void AppMatch::getInstalledAppsVersion(QString appname){
void AppMatch::getInstalledAppsVersion(QString appname) {
// qWarning()<<"apt show "+appname;
// m_versionCommand->start("apt show "+appname);
// m_versionCommand->startDetached(m_versionCommand->program());
@ -360,21 +342,21 @@ void AppMatch::getInstalledAppsVersion(QString appname){
// m_versionCommand->close();
}
void AppMatch::run(){
qDebug()<<"AppMatch is run";
void AppMatch::run() {
qDebug() << "AppMatch is run";
this->getDesktopFilePath();
this->getAllDesktopFilePath("/usr/share/applications/");
QDir androidPath(QDir::homePath()+"/.local/share/applications/");
QDir androidPath(QDir::homePath() + "/.local/share/applications/");
if(androidPath.exists())
this->getAllDesktopFilePath(QDir::homePath()+"/.local/share/applications/");
connect(m_watchAppDir,&QFileSystemWatcher::directoryChanged,this,[=](const QString &path){
this->getAllDesktopFilePath(QDir::homePath() + "/.local/share/applications/");
connect(m_watchAppDir, &QFileSystemWatcher::directoryChanged, this, [ = ](const QString & path) {
this->getDesktopFilePath();
if(path=="/usr/share/applications/"){
this->getAllDesktopFilePath("/usr/share/applications/");
if(path == "/usr/share/applications/") {
this->getAllDesktopFilePath("/usr/share/applications/");
}
if(androidPath.exists()){
if(path==QDir::homePath()+"/.local/share/applications/"){
this->getAllDesktopFilePath(QDir::homePath()+"/.local/share/applications/");
if(androidPath.exists()) {
if(path == QDir::homePath() + "/.local/share/applications/") {
this->getAllDesktopFilePath(QDir::homePath() + "/.local/share/applications/");
}
}
});

View File

@ -30,8 +30,7 @@
#include <QElapsedTimer>
#include <QThread>
class NameString
{
class NameString {
public:
explicit NameString(const QString &str_) : app_name(str_) {}
NameString() = default;
@ -52,25 +51,24 @@ public:
// }
//};
class AppMatch : public QThread
{
class AppMatch : public QThread {
Q_OBJECT
public:
static AppMatch *getAppMatch();
void startMatchApp(QString input,QMap<NameString,QStringList> &installed,QMap<NameString,QStringList> &softwarereturn);
void startMatchApp(QString input, QMap<NameString, QStringList> &installed, QMap<NameString, QStringList> &softwarereturn);
private:
explicit AppMatch(QObject *parent = nullptr);
~AppMatch();
void getAllDesktopFilePath(QString path);
void getDesktopFilePath();
void getAppName(QMap<NameString,QStringList> &installed);
void getAppName(QMap<NameString, QStringList> &installed);
// void appNameMatch(QString appname,QString desktoppath,QString appicon);
void appNameMatch(QString appname,QMap<NameString,QStringList> &installed);
void appNameMatch(QString appname, QMap<NameString, QStringList> &installed);
void softWareCenterSearch(QMap<NameString,QStringList> &softwarereturn);
void softWareCenterSearch(QMap<NameString, QStringList> &softwarereturn);
void parseSoftWareCenterReturn(QList<QMap<QString,QString>> list,QMap<NameString,QStringList> &softwarereturn);
void parseSoftWareCenterReturn(QList<QMap<QString, QString>> list, QMap<NameString, QStringList> &softwarereturn);
void getInstalledAppsVersion(QString appname);
@ -78,12 +76,12 @@ private:
QString m_sourceText;
QStringList m_filePathList;
QDBusInterface *m_interFace=nullptr;
QFileSystemWatcher *m_watchAppDir=nullptr;
QMap<NameString,QStringList> m_installAppMap;
QDBusInterface *m_interFace = nullptr;
QFileSystemWatcher *m_watchAppDir = nullptr;
QMap<NameString, QStringList> m_installAppMap;
private Q_SLOTS:
void slotDBusCallFinished(QMap<NameString,QStringList> &softwarereturn);
void slotDBusCallFinished(QMap<NameString, QStringList> &softwarereturn);
//Q_SIGNALS:

View File

@ -28,13 +28,11 @@ unsigned short FileUtils::_index_status = 0;
FileUtils::SearchMethod FileUtils::searchMethod = FileUtils::SearchMethod::DIRECTSEARCH;
QMap<QString, QStringList> FileUtils::map_chinese2pinyin = QMap<QString, QStringList>();
FileUtils::FileUtils()
{
FileUtils::FileUtils() {
}
std::string FileUtils::makeDocUterm(QString path)
{
return QCryptographicHash::hash(path.toUtf8(),QCryptographicHash::Md5).toHex().toStdString();
std::string FileUtils::makeDocUterm(QString path) {
return QCryptographicHash::hash(path.toUtf8(), QCryptographicHash::Md5).toHex().toStdString();
}
/**
@ -43,30 +41,29 @@ std::string FileUtils::makeDocUterm(QString path)
* @param checkValid
* @return
*/
QIcon FileUtils::getFileIcon(const QString &uri, bool checkValid)
{
QIcon FileUtils::getFileIcon(const QString &uri, bool checkValid) {
auto file = wrapGFile(g_file_new_for_uri(uri.toUtf8().constData()));
auto info = wrapGFileInfo(g_file_query_info(file.get()->get(),
G_FILE_ATTRIBUTE_STANDARD_ICON,
G_FILE_QUERY_INFO_NONE,
nullptr,
nullptr));
if (!G_IS_FILE_INFO (info.get()->get()))
G_FILE_ATTRIBUTE_STANDARD_ICON,
G_FILE_QUERY_INFO_NONE,
nullptr,
nullptr));
if(!G_IS_FILE_INFO(info.get()->get()))
return QIcon::fromTheme("unknown");
GIcon *g_icon = g_file_info_get_icon (info.get()->get());
GIcon *g_icon = g_file_info_get_icon(info.get()->get());
QString icon_name;
//do not unref the GIcon from info.
if (G_IS_ICON(g_icon)) {
const gchar* const* icon_names = g_themed_icon_get_names(G_THEMED_ICON (g_icon));
if (icon_names) {
if(G_IS_ICON(g_icon)) {
const gchar* const* icon_names = g_themed_icon_get_names(G_THEMED_ICON(g_icon));
if(icon_names) {
auto p = icon_names;
if (*p)
icon_name = QString (*p);
if (checkValid) {
while (*p) {
if(*p)
icon_name = QString(*p);
if(checkValid) {
while(*p) {
QIcon icon = QIcon::fromTheme(*p);
if (!icon.isNull()) {
icon_name = QString (*p);
if(!icon.isNull()) {
icon_name = QString(*p);
break;
} else {
p++;
@ -75,7 +72,7 @@ QIcon FileUtils::getFileIcon(const QString &uri, bool checkValid)
}
}
}
if (QIcon::fromTheme(icon_name).isNull()) {
if(QIcon::fromTheme(icon_name).isNull()) {
return QIcon::fromTheme("unknown");
}
return QIcon::fromTheme(icon_name);
@ -91,13 +88,13 @@ QIcon FileUtils::getAppIcon(const QString &path) {
ba = path.toUtf8();
GKeyFile * keyfile;
keyfile = g_key_file_new();
if (!g_key_file_load_from_file(keyfile, ba.data(), G_KEY_FILE_NONE, NULL)){
g_key_file_free (keyfile);
if(!g_key_file_load_from_file(keyfile, ba.data(), G_KEY_FILE_NONE, NULL)) {
g_key_file_free(keyfile);
return QIcon::fromTheme("unknown");
}
QString icon = QString(g_key_file_get_locale_string(keyfile, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_ICON, NULL, NULL));
g_key_file_free(keyfile);
if (QIcon::fromTheme(icon).isNull()) {
if(QIcon::fromTheme(icon).isNull()) {
return QIcon(":/res/icons/desktop.png");
}
return QIcon::fromTheme(icon);
@ -111,17 +108,17 @@ QIcon FileUtils::getAppIcon(const QString &path) {
*/
QIcon FileUtils::getSettingIcon(const QString& setting, const bool& is_white) {
QString name = setting.left(setting.indexOf("/"));
if (! name.isEmpty()) {
if(! name.isEmpty()) {
name.replace(QString(name.at(0)), QString(name.at(0).toUpper()));
}
QString path;
if (is_white) {
if(is_white) {
path = QString("/usr/share/ukui-control-center/shell/res/secondaryleftmenu/%1White.svg").arg(name);
} else {
path = QString("/usr/share/ukui-control-center/shell/res/secondaryleftmenu/%1.svg").arg(name);
}
QFile file(path);
if (file.exists()) {
if(file.exists()) {
return QIcon(path);
} else {
return QIcon::fromTheme("ukui-control-center"); //无插件图标时,返回控制面板应用图标
@ -140,7 +137,7 @@ QIcon FileUtils::getSettingIcon(const QString& setting, const bool& is_white) {
*/
QString FileUtils::getFileName(const QString& uri) {
QFileInfo info(uri);
if (info.exists()) {
if(info.exists()) {
return info.fileName();
} else {
return "Unknown File";
@ -162,8 +159,8 @@ QString FileUtils::getAppName(const QString& path) {
ba = path.toUtf8();
GKeyFile * keyfile;
keyfile = g_key_file_new();
if (!g_key_file_load_from_file(keyfile, ba.data(), G_KEY_FILE_NONE, NULL)){
g_key_file_free (keyfile);
if(!g_key_file_load_from_file(keyfile, ba.data(), G_KEY_FILE_NONE, NULL)) {
g_key_file_free(keyfile);
return "Unknown App";
}
QString name = QString(g_key_file_get_locale_string(keyfile, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, NULL, NULL));
@ -181,10 +178,9 @@ QString FileUtils::getSettingName(const QString& setting) {
}
void FileUtils::loadHanziTable(const QString &fileName)
{
void FileUtils::loadHanziTable(const QString &fileName) {
QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
if(!file.open(QFile::ReadOnly | QFile::Text)) {
qDebug("File: '%s' open failed!", file.fileName().toStdString().c_str());
return;
}
@ -200,25 +196,23 @@ void FileUtils::loadHanziTable(const QString &fileName)
return;
}
QMimeType FileUtils::getMimetype(QString &path)
{
QMimeType FileUtils::getMimetype(QString &path) {
QMimeDatabase mdb;
QMimeType type = mdb.mimeTypeForFile(path,QMimeDatabase::MatchContent);
QMimeType type = mdb.mimeTypeForFile(path, QMimeDatabase::MatchContent);
return type;
}
//aborted
QString FileUtils::find(const QString &hanzi)
{
QString FileUtils::find(const QString &hanzi) {
// static QMap<QString, QStringList> map = loadHanziTable("://index/pinyinWithoutTone.txt");
// static QMap<QString, QStringList> map;
QString output;
QStringList stringList = hanzi.split("");
/* 遍历查找汉字-拼音对照表的内容并将汉字替换为拼音 */
for (const QString &str : stringList) {
if (FileUtils::map_chinese2pinyin.contains(str))
for(const QString &str : stringList) {
if(FileUtils::map_chinese2pinyin.contains(str))
output += FileUtils::map_chinese2pinyin[str].first();
else
output += str;
@ -228,93 +222,88 @@ QString FileUtils::find(const QString &hanzi)
}
//DFS多音字太多直接GG
void stitchMultiToneWordsDFS(const QString& hanzi, const QString& resultAllPinYin, const QString& resultFirst, QStringList& resultList){
if (hanzi.size() == 0){
void stitchMultiToneWordsDFS(const QString& hanzi, const QString& resultAllPinYin, const QString& resultFirst, QStringList& resultList) {
if(hanzi.size() == 0) {
resultList.append(resultAllPinYin);
resultList.append(resultFirst);
return;
}
if (FileUtils::map_chinese2pinyin.contains(hanzi.at(0))){
for (auto i : FileUtils::map_chinese2pinyin[hanzi.at(0)]){
if(FileUtils::map_chinese2pinyin.contains(hanzi.at(0))) {
for(auto i : FileUtils::map_chinese2pinyin[hanzi.at(0)]) {
stitchMultiToneWordsDFS(hanzi.right(hanzi.size() - 1), resultAllPinYin + i, resultFirst + i.at(0), resultList);
}
}
else{
} else {
stitchMultiToneWordsDFS(hanzi.right(hanzi.size() - 1), resultAllPinYin + hanzi.at(0), resultFirst + hanzi.at(0), resultList);
}
}
//BFS+Stack多音字太多会爆栈
void stitchMultiToneWordsBFSStack(const QString& hanzi, QStringList& resultList){
void stitchMultiToneWordsBFSStack(const QString& hanzi, QStringList& resultList) {
QString tempHanzi, resultAllPinYin, resultFirst;
QQueue<QString> tempQueue;
tempHanzi = hanzi;
int tempQueueSize = 0;
if (FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))){
for (auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]){
if(FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))) {
for(auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]) {
tempQueue.enqueue(i);
}
}
else{
} else {
tempQueue.enqueue(tempHanzi.at(0));
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
while (tempHanzi.size() != 0) {
while(tempHanzi.size() != 0) {
tempQueueSize = tempQueue.size();
if (FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))){
for (int j = 0; j < tempQueueSize; ++j){
for (auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]){
if(FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))) {
for(int j = 0; j < tempQueueSize; ++j) {
for(auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]) {
tempQueue.enqueue(tempQueue.head() + i);
}
tempQueue.dequeue();
}
}
else{
for (int j = 0; j < tempQueueSize; ++j){
} else {
for(int j = 0; j < tempQueueSize; ++j) {
tempQueue.enqueue(tempQueue.head() + tempHanzi.at(0));
tempQueue.dequeue();
}
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
}
while(!tempQueue.empty()){
while(!tempQueue.empty()) {
resultList.append(tempQueue.dequeue());
}
}
//BFS+Heap多音字太多会耗尽内存
void stitchMultiToneWordsBFSHeap(const QString& hanzi, QStringList& resultList){
void stitchMultiToneWordsBFSHeap(const QString& hanzi, QStringList& resultList) {
QString tempHanzi, resultAllPinYin, resultFirst;
QQueue<QString>* tempQueue = new QQueue<QString>;
tempHanzi = hanzi;
int tempQueueSize = 0;
if (FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))){
for (auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]){
if(FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))) {
for(auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]) {
tempQueue->enqueue(i);
}
}
else{
} else {
tempQueue->enqueue(tempHanzi.at(0));
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
while (tempHanzi.size() != 0) {
while(tempHanzi.size() != 0) {
tempQueueSize = tempQueue->size();
if (FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))){
for (int j = 0; j < tempQueueSize; ++j){
for (auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]){
if(FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))) {
for(int j = 0; j < tempQueueSize; ++j) {
for(auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]) {
tempQueue->enqueue(tempQueue->head() + i);
}
tempQueue->dequeue();
}
}
else{
for (int j = 0; j < tempQueueSize; ++j){
} else {
for(int j = 0; j < tempQueueSize; ++j) {
tempQueue->enqueue(tempQueue->head() + tempHanzi.at(0));
tempQueue->dequeue();
}
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
}
while(!tempQueue->empty()){
while(!tempQueue->empty()) {
resultList.append(tempQueue->dequeue());
}
delete tempQueue;
@ -322,28 +311,27 @@ void stitchMultiToneWordsBFSHeap(const QString& hanzi, QStringList& resultList){
}
//BFS+Heap+超过3个多音字只建一个索引比较折中的方案
void stitchMultiToneWordsBFSHeapLess3(const QString& hanzi, QStringList& resultList){
void stitchMultiToneWordsBFSHeapLess3(const QString& hanzi, QStringList& resultList) {
QString tempHanzi, resultAllPinYin, resultFirst;
QQueue<QString>* tempQueue = new QQueue<QString>;
QQueue<QString>* tempQueueFirst = new QQueue<QString>;
tempHanzi = hanzi;
int tempQueueSize = 0;
int multiToneWordNum = 0;
for (auto i : hanzi){
if (FileUtils::map_chinese2pinyin.contains(i)){
if (FileUtils::map_chinese2pinyin[i].size() > 1){
for(auto i : hanzi) {
if(FileUtils::map_chinese2pinyin.contains(i)) {
if(FileUtils::map_chinese2pinyin[i].size() > 1) {
++multiToneWordNum;
}
}
}
if (multiToneWordNum > 3){
if(multiToneWordNum > 3) {
QString oneResult, oneResultFirst;
for (auto i : hanzi){
if (FileUtils::map_chinese2pinyin.contains(i)){
for(auto i : hanzi) {
if(FileUtils::map_chinese2pinyin.contains(i)) {
oneResult += FileUtils::map_chinese2pinyin[i].first();
oneResultFirst += FileUtils::map_chinese2pinyin[i].first().at(0);
}
else{
} else {
oneResult += i;
oneResultFirst += i;
}
@ -353,31 +341,29 @@ void stitchMultiToneWordsBFSHeapLess3(const QString& hanzi, QStringList& resultL
return;
}
if (FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))){
for (auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]){
if(FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))) {
for(auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]) {
tempQueue->enqueue(i);
tempQueueFirst->enqueue(i.at(0));
}
}
else{
} else {
tempQueue->enqueue(tempHanzi.at(0));
tempQueueFirst->enqueue(tempHanzi.at(0));
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
while (tempHanzi.size() != 0) {
while(tempHanzi.size() != 0) {
tempQueueSize = tempQueue->size();
if (FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))){
for (int j = 0; j < tempQueueSize; ++j){
for (auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]){
if(FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))) {
for(int j = 0; j < tempQueueSize; ++j) {
for(auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]) {
tempQueue->enqueue(tempQueue->head() + i);
tempQueueFirst->enqueue(tempQueueFirst->head() + i.at(0));
}
tempQueue->dequeue();
tempQueueFirst->dequeue();
}
}
else{
for (int j = 0; j < tempQueueSize; ++j){
} else {
for(int j = 0; j < tempQueueSize; ++j) {
tempQueue->enqueue(tempQueue->head() + tempHanzi.at(0));
tempQueueFirst->enqueue(tempQueueFirst->head() + tempHanzi.at(0));
tempQueue->dequeue();
@ -386,7 +372,7 @@ void stitchMultiToneWordsBFSHeapLess3(const QString& hanzi, QStringList& resultL
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
}
while(!tempQueue->empty()){
while(!tempQueue->empty()) {
resultList.append(tempQueue->dequeue());
resultList.append(tempQueueFirst->dequeue());
}
@ -398,28 +384,27 @@ void stitchMultiToneWordsBFSHeapLess3(const QString& hanzi, QStringList& resultL
}
//BFS+Stack+超过3个多音字只建一个索引比较折中的方案
void stitchMultiToneWordsBFSStackLess3(const QString& hanzi, QStringList& resultList){
void stitchMultiToneWordsBFSStackLess3(const QString& hanzi, QStringList& resultList) {
QString tempHanzi, resultAllPinYin, resultFirst;
QQueue<QString> tempQueue;
QQueue<QString> tempQueueFirst;
tempHanzi = hanzi;
int tempQueueSize = 0;
int multiToneWordNum = 0;
for (auto i : hanzi){
if (FileUtils::map_chinese2pinyin.contains(i)){
if (FileUtils::map_chinese2pinyin[i].size() > 1){
for(auto i : hanzi) {
if(FileUtils::map_chinese2pinyin.contains(i)) {
if(FileUtils::map_chinese2pinyin[i].size() > 1) {
++multiToneWordNum;
}
}
}
if (multiToneWordNum > 3){
if(multiToneWordNum > 3) {
QString oneResult, oneResultFirst;
for (auto i : hanzi){
if (FileUtils::map_chinese2pinyin.contains(i)){
for(auto i : hanzi) {
if(FileUtils::map_chinese2pinyin.contains(i)) {
oneResult += FileUtils::map_chinese2pinyin[i].first();
oneResultFirst += FileUtils::map_chinese2pinyin[i].first().at(0);
}
else{
} else {
oneResult += i;
oneResultFirst += i;
}
@ -429,31 +414,29 @@ void stitchMultiToneWordsBFSStackLess3(const QString& hanzi, QStringList& result
return;
}
if (FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))){
for (auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]){
if(FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))) {
for(auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]) {
tempQueue.enqueue(i);
tempQueueFirst.enqueue(i.at(0));
}
}
else{
} else {
tempQueue.enqueue(tempHanzi.at(0));
tempQueueFirst.enqueue(tempHanzi.at(0));
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
while (tempHanzi.size() != 0) {
while(tempHanzi.size() != 0) {
tempQueueSize = tempQueue.size();
if (FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))){
for (int j = 0; j < tempQueueSize; ++j){
for (auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]){
if(FileUtils::map_chinese2pinyin.contains(tempHanzi.at(0))) {
for(int j = 0; j < tempQueueSize; ++j) {
for(auto i : FileUtils::map_chinese2pinyin[tempHanzi.at(0)]) {
tempQueue.enqueue(tempQueue.head() + i);
tempQueueFirst.enqueue(tempQueueFirst.head() + i.at(0));
}
tempQueue.dequeue();
tempQueueFirst.dequeue();
}
}
else{
for (int j = 0; j < tempQueueSize; ++j){
} else {
for(int j = 0; j < tempQueueSize; ++j) {
tempQueue.enqueue(tempQueue.head() + tempHanzi.at(0));
tempQueueFirst.enqueue(tempQueueFirst.head() + tempHanzi.at(0));
tempQueue.dequeue();
@ -462,7 +445,7 @@ void stitchMultiToneWordsBFSStackLess3(const QString& hanzi, QStringList& result
}
tempHanzi = tempHanzi.right(tempHanzi.size() - 1);
}
while(!tempQueue.empty()){
while(!tempQueue.empty()) {
resultList.append(tempQueue.dequeue());
resultList.append(tempQueueFirst.dequeue());
}
@ -473,8 +456,7 @@ void stitchMultiToneWordsBFSStackLess3(const QString& hanzi, QStringList& result
return;
}
QStringList FileUtils::findMultiToneWords(const QString& hanzi)
{
QStringList FileUtils::findMultiToneWords(const QString& hanzi) {
// QStringList* output = new QStringList();
QStringList output;
QString tempAllPinYin, tempFirst;
@ -491,17 +473,16 @@ QStringList FileUtils::findMultiToneWords(const QString& hanzi)
* @param path: abs path
* @return docx to QString
*/
void FileUtils::getDocxTextContent(QString &path,QString &textcontent)
{
void FileUtils::getDocxTextContent(QString &path, QString &textcontent) {
//fix me :optimized by xpath??
QFileInfo info = QFileInfo(path);
if(!info.exists()||info.isDir())
if(!info.exists() || info.isDir())
return;
QuaZip file(path);
if(!file.open(QuaZip::mdUnzip))
return;
if(!file.setCurrentFile("word/document.xml",QuaZip::csSensitive))
if(!file.setCurrentFile("word/document.xml", QuaZip::csSensitive))
return;
QuaZipFile fileR(&file);
@ -512,18 +493,14 @@ void FileUtils::getDocxTextContent(QString &path,QString &textcontent)
fileR.close();
QDomElement first = doc.firstChildElement("w:document");
QDomElement body = first.firstChildElement("w:body");
while(!body.isNull())
{
QDomElement wp= body.firstChildElement("w:p");
while(!wp.isNull())
{
QDomElement wr= wp.firstChildElement("w:r");
while(!wr.isNull())
{
while(!body.isNull()) {
QDomElement wp = body.firstChildElement("w:p");
while(!wp.isNull()) {
QDomElement wr = wp.firstChildElement("w:r");
while(!wr.isNull()) {
QDomElement wt = wr.firstChildElement("w:t");
textcontent.append(wt.text().replace("\n",""));
if(textcontent.length() >= MAX_CONTENT_LENGTH/3)
{
textcontent.append(wt.text().replace("\n", ""));
if(textcontent.length() >= MAX_CONTENT_LENGTH / 3) {
file.close();
return;
}
@ -537,20 +514,18 @@ void FileUtils::getDocxTextContent(QString &path,QString &textcontent)
return;
}
void FileUtils::getPptxTextContent(QString &path, QString &textcontent)
{
void FileUtils::getPptxTextContent(QString &path, QString &textcontent) {
QFileInfo info = QFileInfo(path);
if(!info.exists()||info.isDir())
if(!info.exists() || info.isDir())
return;
QuaZip file(path);
if(!file.open(QuaZip::mdUnzip))
return;
QString prefix("ppt/slides/slide");
QStringList fileList;
for(QString i : file.getFileNameList())
{
for(QString i : file.getFileNameList()) {
if(i.startsWith(prefix))
fileList<<i;
fileList << i;
}
if(fileList.isEmpty())
return;
@ -562,11 +537,9 @@ void FileUtils::getPptxTextContent(QString &path, QString &textcontent)
QDomDocument doc;
QDomElement at;
// QDomNodeList atList;
for(int i =0;i<fileList.size();++i)
{
QString name = prefix + QString::number(i+1) + ".xml";
if(!file.setCurrentFile(name))
{
for(int i = 0; i < fileList.size(); ++i) {
QString name = prefix + QString::number(i + 1) + ".xml";
if(!file.setCurrentFile(name)) {
continue;
}
QuaZipFile fileR(&file);
@ -595,24 +568,18 @@ void FileUtils::getPptxTextContent(QString &path, QString &textcontent)
// }
//This is ugly but seems more efficient when handel a large file.
sptree = doc.firstChildElement("p:sld").firstChildElement("p:cSld").firstChildElement("p:spTree");
while(!sptree.isNull())
{
sp= sptree.firstChildElement("p:sp");
while(!sp.isNull())
{
txbody= sp.firstChildElement("p:txBody");
while(!txbody.isNull())
{
while(!sptree.isNull()) {
sp = sptree.firstChildElement("p:sp");
while(!sp.isNull()) {
txbody = sp.firstChildElement("p:txBody");
while(!txbody.isNull()) {
ap = txbody.firstChildElement("a:p");
while(!ap.isNull())
{
while(!ap.isNull()) {
ar = ap.firstChildElement("a:r");
while(!ar.isNull())
{
while(!ar.isNull()) {
at = ar.firstChildElement("a:t");
textcontent.append(at.text().replace("\r","")).replace("\t","");
if(textcontent.length() >= MAX_CONTENT_LENGTH/3)
{
textcontent.append(at.text().replace("\r", "")).replace("\t", "");
if(textcontent.length() >= MAX_CONTENT_LENGTH / 3) {
file.close();
return;
}
@ -631,16 +598,15 @@ void FileUtils::getPptxTextContent(QString &path, QString &textcontent)
return;
}
void FileUtils::getXlsxTextContent(QString &path, QString &textcontent)
{
void FileUtils::getXlsxTextContent(QString &path, QString &textcontent) {
QFileInfo info = QFileInfo(path);
if(!info.exists()||info.isDir())
if(!info.exists() || info.isDir())
return;
QuaZip file(path);
if(!file.open(QuaZip::mdUnzip))
return;
if(!file.setCurrentFile("xl/sharedStrings.xml",QuaZip::csSensitive))
if(!file.setCurrentFile("xl/sharedStrings.xml", QuaZip::csSensitive))
return;
QuaZipFile fileR(&file);
@ -653,25 +619,19 @@ void FileUtils::getXlsxTextContent(QString &path, QString &textcontent)
QDomElement si;
QDomElement r;
QDomElement t;
while(!sst.isNull())
{
si= sst.firstChildElement("si");
while(!si.isNull())
{
r= si.firstChildElement("r");
if(r.isNull())
{
t= si.firstChildElement("t");
}
else
{
while(!sst.isNull()) {
si = sst.firstChildElement("si");
while(!si.isNull()) {
r = si.firstChildElement("r");
if(r.isNull()) {
t = si.firstChildElement("t");
} else {
t = r.firstChildElement("t");
}
if(t.isNull())
continue;
textcontent.append(t.text().replace("\r","").replace("\n",""));
if(textcontent.length() >= MAX_CONTENT_LENGTH/3)
{
textcontent.append(t.text().replace("\r", "").replace("\n", ""));
if(textcontent.length() >= MAX_CONTENT_LENGTH / 3) {
file.close();
return;
}
@ -683,46 +643,43 @@ void FileUtils::getXlsxTextContent(QString &path, QString &textcontent)
return;
}
void FileUtils::getPdfTextContent(QString &path, QString &textcontent)
{
void FileUtils::getPdfTextContent(QString &path, QString &textcontent) {
Poppler::Document *doc = Poppler::Document::load(path);
if(doc->isLocked())
return;
const QRectF qf;
int pageNum = doc->numPages();
for(int i = 0; i<pageNum; ++i)
{
textcontent.append(doc->page(i)->text(qf).replace("\n",""));
if(textcontent.length() >= MAX_CONTENT_LENGTH/3)
for(int i = 0; i < pageNum; ++i) {
textcontent.append(doc->page(i)->text(qf).replace("\n", ""));
if(textcontent.length() >= MAX_CONTENT_LENGTH / 3)
break;
}
delete doc;
return;
}
void FileUtils::getTxtContent(QString &path, QString &textcontent)
{
void FileUtils::getTxtContent(QString &path, QString &textcontent) {
QFile file(path);
if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
QByteArray encodedString = file.read(MAX_CONTENT_LENGTH);
uchardet_t chardet = uchardet_new();
if(uchardet_handle_data(chardet,encodedString.constData(),encodedString.size()) !=0)
qWarning()<<"Txt file encoding format detect fail!"<<path;
if(uchardet_handle_data(chardet, encodedString.constData(), encodedString.size()) != 0)
qWarning() << "Txt file encoding format detect fail!" << path;
uchardet_data_end(chardet);
const char *codec = uchardet_get_charset(chardet);
if(QTextCodec::codecForName(codec) == 0)
qWarning()<<"Unsupported Text encoding format"<<path<<QString::fromLocal8Bit(codec);
qWarning() << "Unsupported Text encoding format" << path << QString::fromLocal8Bit(codec);
QTextStream stream(encodedString,QIODevice::ReadOnly);
QTextStream stream(encodedString, QIODevice::ReadOnly);
stream.setCodec(codec);
uchardet_delete(chardet);
textcontent = stream.readAll().replace("\n","");
textcontent = stream.readAll().replace("\n", "");
file.close();
encodedString.clear();

View File

@ -59,10 +59,9 @@
#define UKUI_SEARCH_PIPE_PATH (QDir::homePath()+"/.config/org.ukui/ukui-search/ukuisearch").toLocal8Bit().constData()
class LIBSEARCH_EXPORT FileUtils
{
class LIBSEARCH_EXPORT FileUtils {
public:
static std::string makeDocUterm(QString );
static std::string makeDocUterm(QString);
static QIcon getFileIcon(const QString &, bool checkValid = true);
static QIcon getAppIcon(const QString &);
static QIcon getSettingIcon(const QString &, const bool&);
@ -88,7 +87,7 @@ public:
static size_t _current_index_count; //this one has been Abandoned,do not use it.
static unsigned short _index_status;
enum class SearchMethod{ DIRECTSEARCH = 0, INDEXSEARCH = 1};
enum class SearchMethod { DIRECTSEARCH = 0, INDEXSEARCH = 1};
static SearchMethod searchMethod;
private:

View File

@ -25,43 +25,40 @@
static GlobalSettings *global_instance_of_global_settings = nullptr;
GlobalSettings *GlobalSettings::getInstance()
{
if (!global_instance_of_global_settings) {
GlobalSettings *GlobalSettings::getInstance() {
if(!global_instance_of_global_settings) {
global_instance_of_global_settings = new GlobalSettings;
}
return global_instance_of_global_settings;
}
GlobalSettings::GlobalSettings(QObject *parent) : QObject(parent)
{
GlobalSettings::GlobalSettings(QObject *parent) : QObject(parent) {
m_settings = new QSettings(MAIN_SETTINGS, QSettings::IniFormat, this);
// m_settings->setAtomicSyncRequired(false);
m_block_dirs_settings = new QSettings(BLOCK_DIRS,QSettings::IniFormat, this);
m_block_dirs_settings = new QSettings(BLOCK_DIRS, QSettings::IniFormat, this);
m_block_dirs_settings->setIniCodec(QTextCodec::codecForName("UTF-8"));
m_search_record_settings = new QSettings(SEARCH_HISTORY, QSettings::IniFormat , this);
m_search_record_settings = new QSettings(SEARCH_HISTORY, QSettings::IniFormat, this);
m_search_record_settings->setIniCodec(QTextCodec::codecForName("UTF-8"));
for(QString i:m_search_record_settings->allKeys())
{
for(QString i : m_search_record_settings->allKeys()) {
m_history.append(QUrl::fromPercentEncoding(i.toLocal8Bit()));
}
if(!QDBusConnection::sessionBus().connect("org.kylinssoclient.dbus",
"/org/kylinssoclient/path",
"org.freedesktop.kylinssoclient.interface",
"keyChanged",
this, SLOT(updateSearchHistory(QString))))
"/org/kylinssoclient/path",
"org.freedesktop.kylinssoclient.interface",
"keyChanged",
this, SLOT(updateSearchHistory(QString))))
qWarning()<<"Kylinssoclient Dbus connect fail!";
qWarning() << "Kylinssoclient Dbus connect fail!";
this->forceSync();
//the default number of transparency in mainwindow is 0.7
//if someone changes the num in mainwindow, here should be modified too
m_cache.insert(TRANSPARENCY_KEY, 0.7);
if (QGSettings::isSchemaInstalled(CONTROL_CENTER_PERSONALISE_GSETTINGS_ID)) {
if(QGSettings::isSchemaInstalled(CONTROL_CENTER_PERSONALISE_GSETTINGS_ID)) {
m_trans_gsettings = new QGSettings(CONTROL_CENTER_PERSONALISE_GSETTINGS_ID, QByteArray(), this);
connect(m_trans_gsettings, &QGSettings::changed, this, [=](const QString& key) {
if (key == TRANSPARENCY_KEY) {
connect(m_trans_gsettings, &QGSettings::changed, this, [ = ](const QString & key) {
if(key == TRANSPARENCY_KEY) {
m_cache.remove(TRANSPARENCY_KEY);
m_cache.insert(TRANSPARENCY_KEY, m_trans_gsettings->get(TRANSPARENCY_KEY).toDouble());
qApp->paletteChanged(qApp->palette());
@ -73,15 +70,15 @@ GlobalSettings::GlobalSettings(QObject *parent) : QObject(parent)
m_cache.insert(STYLE_NAME_KEY, "ukui-light");
m_cache.insert(FONT_SIZE_KEY, 11);
if (QGSettings::isSchemaInstalled(THEME_GSETTINGS_ID)) {
if(QGSettings::isSchemaInstalled(THEME_GSETTINGS_ID)) {
m_theme_gsettings = new QGSettings(THEME_GSETTINGS_ID, QByteArray(), this);
connect(m_theme_gsettings, &QGSettings::changed, this, [=](const QString& key) {
if (key == STYLE_NAME_KEY) {
connect(m_theme_gsettings, &QGSettings::changed, this, [ = ](const QString & key) {
if(key == STYLE_NAME_KEY) {
//当前主题改变时也发出paletteChanged信号通知主界面刷新
qApp->paletteChanged(qApp->palette());
m_cache.remove(STYLE_NAME_KEY);
m_cache.insert(STYLE_NAME_KEY, m_theme_gsettings->get(STYLE_NAME_KEY).toString());
} else if (key == FONT_SIZE_KEY) {
} else if(key == FONT_SIZE_KEY) {
qApp->paletteChanged(qApp->palette());
m_cache.remove(FONT_SIZE_KEY);
m_cache.insert(FONT_SIZE_KEY, m_theme_gsettings->get(FONT_SIZE_KEY).toDouble());
@ -94,38 +91,34 @@ GlobalSettings::GlobalSettings(QObject *parent) : QObject(parent)
}
}
const QVariant GlobalSettings::getValue(const QString &key)
{
const QVariant GlobalSettings::getValue(const QString &key) {
return m_cache.value(key);
}
bool GlobalSettings::isExist(const QString &key)
{
bool GlobalSettings::isExist(const QString &key) {
return !m_cache.value(key).isNull();
}
void GlobalSettings::reset(const QString &key)
{
void GlobalSettings::reset(const QString &key) {
m_cache.remove(key);
QtConcurrent::run([=]() {
QtConcurrent::run([ = ]() {
// if (m_mutex.tryLock(1000)) {
m_settings->remove(key);
m_settings->sync();
m_settings->remove(key);
m_settings->sync();
// m_mutex.unlock();
// }
});
Q_EMIT this->valueChanged(key);
}
void GlobalSettings::resetAll()
{
void GlobalSettings::resetAll() {
QStringList tmp = m_cache.keys();
m_cache.clear();
for (auto key : tmp) {
for(auto key : tmp) {
Q_EMIT this->valueChanged(key);
}
QtConcurrent::run([=]() {
if (m_mutex.tryLock(1000)) {
QtConcurrent::run([ = ]() {
if(m_mutex.tryLock(1000)) {
m_settings->clear();
m_settings->sync();
m_mutex.unlock();
@ -133,12 +126,9 @@ void GlobalSettings::resetAll()
});
}
bool GlobalSettings::setBlockDirs(const QString &path, int &returnCode, bool remove)
{
if(remove)
{
if(path.isEmpty())
{
bool GlobalSettings::setBlockDirs(const QString &path, int &returnCode, bool remove) {
if(remove) {
if(path.isEmpty()) {
returnCode = PATH_EMPTY;
return false;
}
@ -146,21 +136,18 @@ bool GlobalSettings::setBlockDirs(const QString &path, int &returnCode, bool rem
m_block_dirs_settings->remove(path);
return true;
}
if(!path.startsWith("/home"))
{
if(!path.startsWith("/home")) {
// returnCode = QString(tr("I can only search your user directory, it doesn't make any sense if you block an directory which is not in user directory!"));
returnCode = PATH_NOT_IN_HOME;
return false;
}
//why QSetting's key can't start with "/"??
QString pathKey = path.right(path.length()-1);
QString pathKey = path.right(path.length() - 1);
QStringList blockDirs = m_block_dirs_settings->allKeys();
for(QString i:blockDirs)
{
if(pathKey.startsWith(i))
{
for(QString i : blockDirs) {
if(pathKey.startsWith(i)) {
// returnCode = QString(tr("My parent folder has been blocked!"));
returnCode = PATH_PARENT_BLOCKED;
return false;
@ -169,12 +156,11 @@ bool GlobalSettings::setBlockDirs(const QString &path, int &returnCode, bool rem
if(i.startsWith(pathKey))
m_block_dirs_settings->remove(i);
}
m_block_dirs_settings->setValue(pathKey,"0");
m_block_dirs_settings->setValue(pathKey, "0");
return true;
}
QStringList GlobalSettings::getBlockDirs()
{
QStringList GlobalSettings::getBlockDirs() {
return m_block_dirs_settings->allKeys();
}
@ -198,19 +184,17 @@ QStringList GlobalSettings::getBlockDirs()
// }
//}
void GlobalSettings::setSearchRecord(const QString &word, const QDateTime &time)
{
void GlobalSettings::setSearchRecord(const QString &word, const QDateTime &time) {
QStringList keys = m_search_record_settings->allKeys();
if(keys.contains(QString(QUrl::toPercentEncoding(word))))
m_history.removeOne(word);
m_search_record_settings->setValue(QString(QUrl::toPercentEncoding(word)), time.toString("yyyy-MM-dd hh:mm:ss"));
m_search_record_settings->setValue(QString(QUrl::toPercentEncoding(word)), time.toString("yyyy-MM-dd hh:mm:ss"));
if(keys.size() >= 20)
m_search_record_settings->remove(QString(QUrl::toPercentEncoding(m_history.takeFirst())));
m_search_record_settings->remove(QString(QUrl::toPercentEncoding(m_history.takeFirst())));
m_history.append(word);
}
QStringList GlobalSettings::getSearchRecord()
{
QStringList GlobalSettings::getSearchRecord() {
return m_history;
}
@ -263,12 +247,11 @@ QStringList GlobalSettings::getSearchRecord()
//here should be override
//MouseZhangZh
void GlobalSettings::setValue(const QString &key, const QVariant &value)
{
void GlobalSettings::setValue(const QString &key, const QVariant &value) {
// qDebug()<<"setvalue========"<<key<<":"<<value;
m_cache.insert(key, value);
// m_settings->sync();
QtConcurrent::run([=]() {
QtConcurrent::run([ = ]() {
// qDebug()<<m_settings->status();
// if (m_mutex.tryLock(1000)) {
// m_mutex.lock();
@ -281,12 +264,11 @@ void GlobalSettings::setValue(const QString &key, const QVariant &value)
});
}
void GlobalSettings::forceSync(const QString &key)
{
void GlobalSettings::forceSync(const QString &key) {
m_settings->sync();
if (key.isNull()) {
if(key.isNull()) {
m_cache.clear();
for (auto key : m_settings->allKeys()) {
for(auto key : m_settings->allKeys()) {
m_cache.insert(key, m_settings->value(key));
}
} else {
@ -295,14 +277,11 @@ void GlobalSettings::forceSync(const QString &key)
}
}
void GlobalSettings::updateSearchHistory(QString key)
{
if(key == "search")
{
void GlobalSettings::updateSearchHistory(QString key) {
if(key == "search") {
m_search_record_settings->sync();
m_history.clear();
for(QString i:m_search_record_settings->allKeys())
{
for(QString i : m_search_record_settings->allKeys()) {
m_history.append(QUrl::fromPercentEncoding(i.toLocal8Bit()));
}
}

View File

@ -56,8 +56,7 @@
//#define CLOUD_HISTORY "history"
//#define CLOUD_APPLICATIONS "applications"
class LIBSEARCH_EXPORT GlobalSettings : public QObject
{
class LIBSEARCH_EXPORT GlobalSettings : public QObject {
Q_OBJECT
public:
static GlobalSettings *getInstance();
@ -65,8 +64,8 @@ public:
bool isExist(const QString&);
Q_SIGNALS:
void valueChanged (const QString&);
void transparencyChanged (const double&);
void valueChanged(const QString&);
void transparencyChanged(const double&);
public Q_SLOTS:
void setValue(const QString&, const QVariant&);
@ -80,7 +79,7 @@ public Q_SLOTS:
* @param true to remove blocking,false to set blocking,default set false.
* @return
*/
bool setBlockDirs(const QString& path, int &returnCode,bool remove = false);
bool setBlockDirs(const QString& path, int &returnCode, bool remove = false);
QStringList getBlockDirs();
// void appendCloudData(const QString& key, const QString& value);
void setSearchRecord(const QString &word, const QDateTime &time);

View File

@ -25,21 +25,20 @@
template<class T>
class gobjecttemplate
{
class gobjecttemplate {
public:
//do not use this constructor.
gobjecttemplate();
gobjecttemplate(T *obj, bool ref = false) {
m_obj = obj;
if (ref) {
if(ref) {
g_object_ref(obj);
}
}
~gobjecttemplate() {
//qDebug()<<"~GObjectTemplate";
if (m_obj)
if(m_obj)
g_object_unref(m_obj);
}

View File

@ -27,16 +27,14 @@
//extern QList<Document> *_doc_list_path;
//extern QMutex _mutex_doc_list_path;
ConstructDocumentForPath::ConstructDocumentForPath(QVector<QString> list)
{
ConstructDocumentForPath::ConstructDocumentForPath(QVector<QString> list) {
this->setAutoDelete(true);
m_list = std::move(list);
}
void ConstructDocumentForPath::run()
{
void ConstructDocumentForPath::run() {
// qDebug()<<"ConstructDocumentForPath";
if (!_doc_list_path)
if(!_doc_list_path)
_doc_list_path = new QList<Document>;
// qDebug()<<_doc_list_path->size();
QString index_text = m_list.at(0).toLower();
@ -45,7 +43,7 @@ void ConstructDocumentForPath::run()
//多音字版
//现加入首字母
QStringList pinyin_text_list = FileUtils::findMultiToneWords(QString(m_list.at(0)).replace(".",""));
QStringList pinyin_text_list = FileUtils::findMultiToneWords(QString(m_list.at(0)).replace(".", ""));
// if(!pinyin_text_list.isEmpty())
// {
// for (QString& i : pinyin_text_list){
@ -56,7 +54,7 @@ void ConstructDocumentForPath::run()
// }
QString uniqueterm = QString::fromStdString(FileUtils::makeDocUterm(sourcePath));
QString upTerm = QString::fromStdString(FileUtils::makeDocUterm(sourcePath.section("/",0,-2,QString::SectionIncludeLeadingSep)));
QString upTerm = QString::fromStdString(FileUtils::makeDocUterm(sourcePath.section("/", 0, -2, QString::SectionIncludeLeadingSep)));
// qDebug()<<"sourcePath"<<sourcePath.section("/",0,-2,QString::SectionIncludeLeadingSep);
// qDebug() << "sourcePath ---------------------------: " << sourcePath;
// qDebug() << "sourcePath.section -------------------: " << sourcePath.section("/",0,-2,QString::SectionIncludeLeadingSep);
@ -68,24 +66,21 @@ void ConstructDocumentForPath::run()
doc.setUniqueTerm(uniqueterm);
doc.addTerm(upTerm);
doc.addValue(m_list.at(2));
/* QStringList temp;
// temp.append(index_text);
temp.append(pinyin_text_list)*/;
/* QStringList temp;
// temp.append(index_text);
temp.append(pinyin_text_list)*/;
int postingCount = 0;
while(postingCount < index_text.size())
{
while(postingCount < index_text.size()) {
// QVector<size_t> p;
// p.append(postingCount);
doc.addPosting(QUrl::toPercentEncoding(index_text.at(postingCount)).toStdString(),postingCount);
doc.addPosting(QUrl::toPercentEncoding(index_text.at(postingCount)).toStdString(), postingCount);
++postingCount;
}
int i = 0;
for (QString& s : pinyin_text_list)
{
for(QString& s : pinyin_text_list) {
i = 0;
while(i < s.size())
{
doc.addPosting(QUrl::toPercentEncoding(s.at(i)).toStdString(),postingCount);
while(i < s.size()) {
doc.addPosting(QUrl::toPercentEncoding(s.at(i)).toStdString(), postingCount);
++postingCount;
++i;
}
@ -99,24 +94,22 @@ void ConstructDocumentForPath::run()
return;
}
ConstructDocumentForContent::ConstructDocumentForContent(QString path)
{
ConstructDocumentForContent::ConstructDocumentForContent(QString path) {
this->setAutoDelete(true);
m_path = std::move(path);
}
void ConstructDocumentForContent::run()
{
void ConstructDocumentForContent::run() {
// qDebug() << "ConstructDocumentForContent currentThreadId()" << QThread::currentThreadId();
// 构造文本索引的document
if (!_doc_list_content)
if(!_doc_list_content)
_doc_list_content = new QList<Document>;
QString content;
FileReader::getTextContent(m_path,content);
FileReader::getTextContent(m_path, content);
if(content.isEmpty())
return;
QString uniqueterm = QString::fromStdString(FileUtils::makeDocUterm(m_path));
QString upTerm = QString::fromStdString(FileUtils::makeDocUterm(m_path.section("/",0,-2,QString::SectionIncludeLeadingSep)));
QString upTerm = QString::fromStdString(FileUtils::makeDocUterm(m_path.section("/", 0, -2, QString::SectionIncludeLeadingSep)));
QVector<SKeyWord> term = ChineseSegmentation::getInstance()->callSegement(content.left(20480000));
@ -125,9 +118,8 @@ void ConstructDocumentForContent::run()
doc.setUniqueTerm(uniqueterm);
doc.addTerm(upTerm);
doc.addValue(m_path);
for(int i = 0;i<term.size();++i)
{
doc.addPosting(term.at(i).word,term.at(i).offsets,static_cast<int>(term.at(i).weight));
for(int i = 0; i < term.size(); ++i) {
doc.addPosting(term.at(i).word, term.at(i).offsets, static_cast<int>(term.at(i).weight));
}

View File

@ -28,8 +28,7 @@
//extern QList<Document> *_doc_list_path;
//extern QMutex _mutex_doc_list_path;
class IndexGenerator;
class ConstructDocumentForPath : public QRunnable
{
class ConstructDocumentForPath : public QRunnable {
public:
explicit ConstructDocumentForPath(QVector<QString> list);
~ConstructDocumentForPath() = default;
@ -39,8 +38,7 @@ private:
QVector<QString> m_list;
};
class ConstructDocumentForContent : public QRunnable
{
class ConstructDocumentForContent : public QRunnable {
public:
explicit ConstructDocumentForContent(QString path);
~ConstructDocumentForContent() = default;

View File

@ -20,50 +20,43 @@
#include "document.h"
#include <QDebug>
void Document::setData(QString data)
{
void Document::setData(QString data) {
if(data.isEmpty())
return;
m_document.set_data(data.toStdString());
}
void Document::addPosting(std::string term,QVector<size_t> offset, int weight)
{
void Document::addPosting(std::string term, QVector<size_t> offset, int weight) {
if(term == "")
return;
if(term.length() > 240)
term = QString::fromStdString(term).left(30).toStdString();
for(size_t i : offset)
{
m_document.add_posting(term,i,weight);
for(size_t i : offset) {
m_document.add_posting(term, i, weight);
}
}
void Document::addPosting(std::string term, unsigned int offset, int weight)
{
void Document::addPosting(std::string term, unsigned int offset, int weight) {
if(term == "")
return;
if(term.length() > 240)
term = QString::fromStdString(term).left(30).toStdString();
m_document.add_posting(term,offset,weight);
m_document.add_posting(term, offset, weight);
}
void Document::addTerm(QString term)
{
void Document::addTerm(QString term) {
if(term.isEmpty())
return;
m_document.add_term(term.toStdString());
}
void Document::addValue(QString value)
{
m_document.add_value(1,value.toStdString());
void Document::addValue(QString value) {
m_document.add_value(1, value.toStdString());
}
void Document::setUniqueTerm(QString term)
{
void Document::setUniqueTerm(QString term) {
if(term.isEmpty())
return;
m_document.add_term(term.toStdString());
@ -71,26 +64,22 @@ void Document::setUniqueTerm(QString term)
// m_unique_term = new QString(term);
m_unique_term = std::move(term);
}
std::string Document::getUniqueTerm()
{
std::string Document::getUniqueTerm() {
// qDebug()<<"m_unique_term!"<<*m_unique_term;
// qDebug() << QString::fromStdString(m_unique_term.toStdString());
return m_unique_term.toStdString();
}
void Document::setIndexText(QStringList indexText)
{
void Document::setIndexText(QStringList indexText) {
// QStringList indexTextList = indexText;
// m_index_text = new QStringList(indexText);
m_index_text = std::move(indexText);
}
QStringList Document::getIndexText()
{
QStringList Document::getIndexText() {
return m_index_text;
}
Xapian::Document Document::getXapianDocument()
{
Xapian::Document Document::getXapianDocument() {
return m_document;
}

View File

@ -25,24 +25,23 @@
#include <QStringList>
#include <QVector>
class Document
{
class Document {
public:
Document() = default;
~Document(){}
Document(const Document& other){
~Document() {}
Document(const Document& other) {
m_document = other.m_document;
m_index_text = other.m_index_text;
m_unique_term = other.m_unique_term;
}
void operator=(const Document& other){
m_document = other.m_document;
m_index_text = other.m_index_text;
m_unique_term = other.m_unique_term;
void operator=(const Document& other) {
m_document = other.m_document;
m_index_text = other.m_index_text;
m_unique_term = other.m_unique_term;
}
void setData(QString data);
void addPosting(std::string term, QVector<size_t> offset, int weight =1);
void addPosting(std::string term, unsigned int offset, int weight =1);
void addPosting(std::string term, QVector<size_t> offset, int weight = 1);
void addPosting(std::string term, unsigned int offset, int weight = 1);
void addTerm(QString term);
void addValue(QString value);
void setUniqueTerm(QString term);

View File

@ -21,48 +21,36 @@
#include "file-utils.h"
#include "binary-parser.h"
FileReader::FileReader(QObject *parent) : QObject(parent)
{
FileReader::FileReader(QObject *parent) : QObject(parent) {
}
void FileReader::getTextContent(QString path, QString &textContent)
{
void FileReader::getTextContent(QString path, QString &textContent) {
QMimeType type = FileUtils::getMimetype(path);
QString name = type.name();
QFileInfo file(path);
QString strsfx = file.suffix();
if(name== "application/zip")
{
if(strsfx.endsWith( "docx"))
FileUtils::getDocxTextContent(path,textContent);
if(strsfx.endsWith( "pptx"))
FileUtils::getPptxTextContent(path,textContent);
if(strsfx.endsWith( "xlsx"))
FileUtils::getXlsxTextContent(path,textContent);
}
else if(name == "text/plain")
{
if(strsfx.endsWith( "txt"))
FileUtils::getTxtContent(path,textContent);
}
else if(type.inherits("application/msword") || type.name() == "application/x-ole-storage")
{
if (strsfx.endsWith("doc") || strsfx.endsWith("dot") || strsfx.endsWith("wps") || strsfx.endsWith("ppt") ||
strsfx.endsWith("pps") ||strsfx.endsWith("dps") || strsfx.endsWith("et") || strsfx.endsWith("xls"))
{
if(name == "application/zip") {
if(strsfx.endsWith("docx"))
FileUtils::getDocxTextContent(path, textContent);
if(strsfx.endsWith("pptx"))
FileUtils::getPptxTextContent(path, textContent);
if(strsfx.endsWith("xlsx"))
FileUtils::getXlsxTextContent(path, textContent);
} else if(name == "text/plain") {
if(strsfx.endsWith("txt"))
FileUtils::getTxtContent(path, textContent);
} else if(type.inherits("application/msword") || type.name() == "application/x-ole-storage") {
if(strsfx.endsWith("doc") || strsfx.endsWith("dot") || strsfx.endsWith("wps") || strsfx.endsWith("ppt") ||
strsfx.endsWith("pps") || strsfx.endsWith("dps") || strsfx.endsWith("et") || strsfx.endsWith("xls")) {
KBinaryParser searchdata;
searchdata.RunParser(path,textContent);
searchdata.RunParser(path, textContent);
}
}
else if(name == "application/pdf")
{
if(strsfx.endsWith( "pdf"))
FileUtils::getPdfTextContent(path,textContent);
}
else
{
qWarning()<<"Unsupport format:["<<path<<"]["<<type.name()<<"]";
} else if(name == "application/pdf") {
if(strsfx.endsWith("pdf"))
FileUtils::getPdfTextContent(path, textContent);
} else {
qWarning() << "Unsupport format:[" << path << "][" << type.name() << "]";
}
return;

View File

@ -23,12 +23,11 @@
#include <QObject>
#include <QFileInfo>
class FileReader : public QObject
{
class FileReader : public QObject {
Q_OBJECT
public:
explicit FileReader(QObject *parent = nullptr);
~FileReader()=default;
~FileReader() = default;
static void getTextContent(QString path, QString &textContent);
};

View File

@ -32,30 +32,23 @@ size_t FileSearcher::uniqueSymbol3 = 0;
QMutex FileSearcher::m_mutex1;
QMutex FileSearcher::m_mutex2;
QMutex FileSearcher::m_mutex3;
FileSearcher::FileSearcher(QObject *parent) : QObject(parent)
{
FileSearcher::FileSearcher(QObject *parent) : QObject(parent) {
}
FileSearcher::~FileSearcher()
{
FileSearcher::~FileSearcher() {
}
int FileSearcher::getCurrentIndexCount()
{
try
{
int FileSearcher::getCurrentIndexCount() {
try {
Xapian::Database db(INDEX_PATH);
return db.get_doccount();
}
catch(const Xapian::Error &e)
{
qWarning() <<QString::fromStdString(e.get_description());
} catch(const Xapian::Error &e) {
qWarning() << QString::fromStdString(e.get_description());
return 0;
}
}
void FileSearcher::onKeywordSearch(QString keyword,QQueue<QString> *searchResultFile,QQueue<QString> *searchResultDir,QQueue<QPair<QString,QStringList>> *searchResultContent)
{
void FileSearcher::onKeywordSearch(QString keyword, QQueue<QString> *searchResultFile, QQueue<QString> *searchResultDir, QQueue<QPair<QString, QStringList>> *searchResultContent) {
m_mutex1.lock();
++uniqueSymbol1;
m_mutex1.unlock();
@ -71,16 +64,15 @@ void FileSearcher::onKeywordSearch(QString keyword,QQueue<QString> *searchResult
m_search_result_content = searchResultContent;
//file
QtConcurrent::run([&, uniqueSymbol1, keyword](){
QtConcurrent::run([&, uniqueSymbol1, keyword]() {
if(!m_search_result_file->isEmpty())
m_search_result_file->clear();
int begin = 0;
int num = 5;
int resultCount = 0;
int total = 0;
while(total < 100)
{
resultCount = keywordSearchfile(uniqueSymbol1,keyword,"0",1,begin,num);
while(total < 100) {
resultCount = keywordSearchfile(uniqueSymbol1, keyword, "0", 1, begin, num);
if(resultCount == 0 || resultCount == -1)
break;
total += resultCount;
@ -90,16 +82,15 @@ void FileSearcher::onKeywordSearch(QString keyword,QQueue<QString> *searchResult
});
// Q_EMIT this->resultFile(m_search_result_file);
//dir
QtConcurrent::run([&, uniqueSymbol2, keyword](){
QtConcurrent::run([&, uniqueSymbol2, keyword]() {
if(!m_search_result_dir->isEmpty())
m_search_result_dir->clear();
int begin = 0;
int num = 5;
int resultCount = 0;
int total = 0;
while(total<100)
{
resultCount = keywordSearchfile(uniqueSymbol2,keyword,"1",1,begin,num);
while(total < 100) {
resultCount = keywordSearchfile(uniqueSymbol2, keyword, "1", 1, begin, num);
if(resultCount == 0 || resultCount == -1)
break;
total += resultCount;
@ -109,7 +100,7 @@ void FileSearcher::onKeywordSearch(QString keyword,QQueue<QString> *searchResult
});
// Q_EMIT this->resultDir(m_search_result_dir);
//content
QtConcurrent::run([&, uniqueSymbol3, keyword](){
QtConcurrent::run([&, uniqueSymbol3, keyword]() {
if(!m_search_result_content->isEmpty())
m_search_result_content->clear();
int begin = 0;
@ -117,9 +108,8 @@ void FileSearcher::onKeywordSearch(QString keyword,QQueue<QString> *searchResult
int resultCount = 0;
int total = 0;
while(total<50)
{
resultCount = keywordSearchContent(uniqueSymbol3,keyword,begin,num);
while(total < 50) {
resultCount = keywordSearchContent(uniqueSymbol3, keyword, begin, num);
if(resultCount == 0 || resultCount == -1)
break;
total += resultCount;
@ -130,54 +120,45 @@ void FileSearcher::onKeywordSearch(QString keyword,QQueue<QString> *searchResult
// Q_EMIT this->resultContent(m_search_result_content);
}
int FileSearcher::keywordSearchfile(size_t uniqueSymbol, QString keyword, QString value, unsigned slot, int begin, int num)
{
try
{
int FileSearcher::keywordSearchfile(size_t uniqueSymbol, QString keyword, QString value, unsigned slot, int begin, int num) {
try {
qDebug() << "--keywordSearchfile start--";
Xapian::Database db(INDEX_PATH);
Xapian::Query query = creatQueryForFileSearch(keyword,db);
Xapian::Query query = creatQueryForFileSearch(keyword, db);
Xapian::Enquire enquire(db);
Xapian::Query queryFile;
if(!value.isEmpty())
{
if(!value.isEmpty()) {
std::string slotValue = value.toStdString();
Xapian::Query queryValue = Xapian::Query(Xapian::Query::OP_VALUE_RANGE,slot,slotValue,slotValue);
queryFile = Xapian::Query(Xapian::Query::OP_AND,query,queryValue);
}
else
{
Xapian::Query queryValue = Xapian::Query(Xapian::Query::OP_VALUE_RANGE, slot, slotValue, slotValue);
queryFile = Xapian::Query(Xapian::Query::OP_AND, query, queryValue);
} else {
queryFile = query;
}
qDebug() << "keywordSearchfile:"<<QString::fromStdString(queryFile.get_description());
qDebug() << "keywordSearchfile:" << QString::fromStdString(queryFile.get_description());
enquire.set_query(queryFile);
Xapian::MSet result = enquire.get_mset(begin, num);
int resultCount = result.size();
qDebug()<< "keywordSearchfile results count=" <<resultCount;
qDebug() << "keywordSearchfile results count=" << resultCount;
if(result.size() == 0)
return 0;
if(getResult(uniqueSymbol, result, value) == -1)
return -1;
qDebug()<< "--keywordSearchfile finish--";
qDebug() << "--keywordSearchfile finish--";
return resultCount;
}
catch(const Xapian::Error &e)
{
qWarning() <<QString::fromStdString(e.get_description());
qDebug()<< "--keywordSearchfile finish--";
} catch(const Xapian::Error &e) {
qWarning() << QString::fromStdString(e.get_description());
qDebug() << "--keywordSearchfile finish--";
return -1;
}
}
int FileSearcher::keywordSearchContent(size_t uniqueSymbol, QString keyword, int begin, int num)
{
try
{
qDebug()<<"--keywordSearchContent search start--";
int FileSearcher::keywordSearchContent(size_t uniqueSymbol, QString keyword, int begin, int num) {
try {
qDebug() << "--keywordSearchContent search start--";
Xapian::Database db(CONTENT_INDEX_PATH);
Xapian::Enquire enquire(db);
@ -188,8 +169,7 @@ int FileSearcher::keywordSearchContent(size_t uniqueSymbol, QString keyword, int
QVector<SKeyWord> sKeyWord = ChineseSegmentation::getInstance()->callSegement(keyword);
//Creat a query
std::string words;
for(int i=0;i<sKeyWord.size();i++)
{
for(int i = 0; i < sKeyWord.size(); i++) {
words.append(sKeyWord.at(i).word).append(" ");
}
Xapian::Query query = qp.parse_query(words);
@ -201,7 +181,7 @@ int FileSearcher::keywordSearchContent(size_t uniqueSymbol, QString keyword, int
// qDebug()<<QString::fromStdString(sKeyWord.at(i).word);
// }
// Xapian::Query queryPhrase =Xapian::Query(Xapian::Query::OP_AND, v.begin(), v.end());
qDebug()<<"keywordSearchContent:"<<QString::fromStdString(query.get_description());
qDebug() << "keywordSearchContent:" << QString::fromStdString(query.get_description());
enquire.set_query(query);
@ -209,23 +189,20 @@ int FileSearcher::keywordSearchContent(size_t uniqueSymbol, QString keyword, int
int resultCount = result.size();
if(result.size() == 0)
return 0;
qDebug()<< "keywordSearchContent results count=" <<resultCount;
qDebug() << "keywordSearchContent results count=" << resultCount;
if(getContentResult(uniqueSymbol, result, words) == -1)
return -1;
qDebug()<< "--keywordSearchContent search finish--";
qDebug() << "--keywordSearchContent search finish--";
return resultCount;
}
catch(const Xapian::Error &e)
{
qWarning() <<QString::fromStdString(e.get_description());
qDebug()<< "--keywordSearchContent search finish--";
} catch(const Xapian::Error &e) {
qWarning() << QString::fromStdString(e.get_description());
qDebug() << "--keywordSearchContent search finish--";
return -1;
}
}
Xapian::Query FileSearcher::creatQueryForFileSearch(QString keyword, Xapian::Database &db)
{
Xapian::Query FileSearcher::creatQueryForFileSearch(QString keyword, Xapian::Database &db) {
// Xapian::QueryParser qp;
// qp.set_default_op(Xapian::Query::OP_PHRASE);
// qp.set_database(db);
@ -241,12 +218,11 @@ Xapian::Query FileSearcher::creatQueryForFileSearch(QString keyword, Xapian::Dat
//Creat a query
// Xapian::Query queryPhrase = qp.parse_query(userInput.toStdString(),Xapian::QueryParser::FLAG_PHRASE|Xapian::QueryParser::FLAG_SYNONYM);
std::vector<Xapian::Query> v;
for(int i=0;i<userInput.size();i++)
{
for(int i = 0; i < userInput.size(); i++) {
v.push_back(Xapian::Query(QUrl::toPercentEncoding(userInput.at(i)).toStdString()));
// qDebug()<<QString::fromStdString(Xapian::Query(QString(userInput.at(i)).toStdString()).get_description());
}
Xapian::Query queryPhrase =Xapian::Query(Xapian::Query::OP_PHRASE, v.begin(), v.end());
Xapian::Query queryPhrase = Xapian::Query(Xapian::Query::OP_PHRASE, v.begin(), v.end());
// Xapian::Query queryNear =Xapian::Query(Xapian::Query::OP_NEAR, v.begin(), v.end());
// Xapian::Query query = Xapian::Query(Xapian::Query::OP_AND,queryNear,queryPhrase);
@ -254,20 +230,17 @@ Xapian::Query FileSearcher::creatQueryForFileSearch(QString keyword, Xapian::Dat
return queryPhrase;
}
Xapian::Query FileSearcher::creatQueryForContentSearch(QString keyword, Xapian::Database &db)
{
Xapian::Query FileSearcher::creatQueryForContentSearch(QString keyword, Xapian::Database &db) {
}
int FileSearcher::getResult(size_t uniqueSymbol, Xapian::MSet &result, QString value)
{
int FileSearcher::getResult(size_t uniqueSymbol, Xapian::MSet &result, QString value) {
//QStringList *pathTobeDelete = new QStringList;
//Delete those path doc which is not already exist.
// QStringList searchResult = QStringList();
for (auto it = result.begin(); it != result.end(); ++it)
{
for(auto it = result.begin(); it != result.end(); ++it) {
Xapian::Document doc = it.get_document();
std::string data = doc.get_data();
Xapian::weight docScoreWeight = it.get_weight();
@ -279,24 +252,17 @@ int FileSearcher::getResult(size_t uniqueSymbol, Xapian::MSet &result, QString v
QFileInfo info(path);
if(!info.exists())
{
if(!info.exists()) {
// pathTobeDelete->append(QString::fromStdString(data));
qDebug()<<path<<"is not exist!!";
}
else
{
switch (value.toInt())
{
qDebug() << path << "is not exist!!";
} else {
switch(value.toInt()) {
case 1:
m_mutex1.lock();
if(uniqueSymbol == FileSearcher::uniqueSymbol1)
{
if(uniqueSymbol == FileSearcher::uniqueSymbol1) {
m_search_result_dir->enqueue(path);
m_mutex1.unlock();
}
else
{
} else {
m_mutex1.unlock();
return -1;
}
@ -304,13 +270,10 @@ int FileSearcher::getResult(size_t uniqueSymbol, Xapian::MSet &result, QString v
break;
case 0:
m_mutex2.lock();
if(uniqueSymbol == FileSearcher::uniqueSymbol2)
{
if(uniqueSymbol == FileSearcher::uniqueSymbol2) {
m_search_result_file->enqueue(path);
m_mutex2.unlock();
}
else
{
} else {
m_mutex2.unlock();
return -1;
}
@ -320,27 +283,25 @@ int FileSearcher::getResult(size_t uniqueSymbol, Xapian::MSet &result, QString v
}
// searchResult.append(path);
}
qDebug()<< "doc="<< path << ",weight=" <<docScoreWeight << ",percent=" << docScorePercent;
qDebug() << "doc=" << path << ",weight=" << docScoreWeight << ",percent=" << docScorePercent;
}
// if(!pathTobeDelete->isEmpty())
// deleteAllIndex(pathTobeDelete)
return 0;
}
int FileSearcher::getContentResult(size_t uniqueSymbol, Xapian::MSet &result, std::string &keyWord)
{
int FileSearcher::getContentResult(size_t uniqueSymbol, Xapian::MSet &result, std::string &keyWord) {
//QStringList *pathTobeDelete = new QStringList;
//Delete those path doc which is not already exist.
QString wordTobeFound = QString::fromStdString(keyWord).section(" ",0,0);
QString wordTobeFound = QString::fromStdString(keyWord).section(" ", 0, 0);
int size = wordTobeFound.size();
int totalSize = QString::fromStdString(keyWord).size();
if(totalSize < 5)
totalSize = 5;
// QMap<QString,QStringList> searchResult;
for (auto it = result.begin(); it != result.end(); ++it)
{
for(auto it = result.begin(); it != result.end(); ++it) {
Xapian::Document doc = it.get_document();
std::string data = doc.get_data();
double docScoreWeight = it.get_weight();
@ -352,50 +313,43 @@ int FileSearcher::getContentResult(size_t uniqueSymbol, Xapian::MSet &result, st
QFileInfo info(path);
if(!info.exists())
{
if(!info.exists()) {
// pathTobeDelete->append(QString::fromStdString(data));
qDebug()<<path<<"is not exist!!";
qDebug() << path << "is not exist!!";
continue;
}
// Construct snippets containing keyword.
QStringList snippets;
auto term = doc.termlist_begin();
term.skip_to(wordTobeFound.toStdString());
int count =0;
for(auto pos = term.positionlist_begin();pos != term.positionlist_end()&&count < 6;++pos)
{
int count = 0;
for(auto pos = term.positionlist_begin(); pos != term.positionlist_end() && count < 6; ++pos) {
QByteArray snippetByte = QByteArray::fromStdString(data);
QString snippet = "..."+QString(snippetByte.left(*pos)).right(size +totalSize) + QString(snippetByte.mid(*pos,-1)).left(size+totalSize) + "...";
QString snippet = "..." + QString(snippetByte.left(*pos)).right(size + totalSize) + QString(snippetByte.mid(*pos, -1)).left(size + totalSize) + "...";
// qDebug()<<snippet;
snippets.append(snippet);
++count;
}
m_mutex3.lock();
if(uniqueSymbol == FileSearcher::uniqueSymbol3)
{
if(uniqueSymbol == FileSearcher::uniqueSymbol3) {
m_search_result_content->enqueue(qMakePair(path,snippets));
m_search_result_content->enqueue(qMakePair(path, snippets));
m_mutex3.unlock();
}
else
{
} else {
m_mutex3.unlock();
return -1;
}
// searchResult.insert(path,snippets);
qDebug()<< "path="<< path << ",weight=" <<docScoreWeight << ",percent=" << docScorePercent;
qDebug() << "path=" << path << ",weight=" << docScoreWeight << ",percent=" << docScorePercent;
}
// if(!pathTobeDelete->isEmpty())
// deleteAllIndex(pathTobeDelete)
return 0;
}
bool FileSearcher::isBlocked(QString &path)
{
bool FileSearcher::isBlocked(QString &path) {
QStringList blockList = GlobalSettings::getInstance()->getBlockDirs();
for(QString i : blockList)
{
for(QString i : blockList) {
if(path.startsWith(i.prepend("/")))
return true;
}

View File

@ -32,8 +32,7 @@
#define CONTENT_INDEX_PATH (QStandardPaths::writableLocation(QStandardPaths::HomeLocation)+"/.config/org.ukui/ukui-search/content_index_data").toStdString()
class FileSearcher : public QObject
{
class FileSearcher : public QObject {
Q_OBJECT
public:
explicit FileSearcher(QObject *parent = nullptr);
@ -49,14 +48,14 @@ public:
static QMutex m_mutex3;
public Q_SLOTS:
void onKeywordSearch(QString keyword,QQueue<QString> *searchResultFile,QQueue<QString> *searchResultDir,QQueue<QPair<QString,QStringList>> *searchResultContent);
void onKeywordSearch(QString keyword, QQueue<QString> *searchResultFile, QQueue<QString> *searchResultDir, QQueue<QPair<QString, QStringList>> *searchResultContent);
Q_SIGNALS:
void resultFile(QQueue<QString> *);
void resultDir(QQueue<QString> *);
void resultContent(QQueue<QPair<QString,QStringList>> *);
void resultContent(QQueue<QPair<QString, QStringList>> *);
private:
int keywordSearchfile(size_t uniqueSymbol, QString keyword, QString value,unsigned slot = 1,int begin = 0, int num = 20);
int keywordSearchfile(size_t uniqueSymbol, QString keyword, QString value, unsigned slot = 1, int begin = 0, int num = 20);
int keywordSearchContent(size_t uniqueSymbol, QString keyword, int begin = 0, int num = 20);
/**
@ -70,13 +69,13 @@ private:
Xapian::Query creatQueryForContentSearch(QString keyword, Xapian::Database &db);
int getResult(size_t uniqueSymbol, Xapian::MSet &result, QString value);
int getContentResult(size_t uniqueSymbol, Xapian::MSet &result,std::string &keyWord);
int getContentResult(size_t uniqueSymbol, Xapian::MSet &result, std::string &keyWord);
bool isBlocked(QString &path);
QQueue<QString> *m_search_result_file = nullptr;
QQueue<QString> *m_search_result_dir = nullptr;
QQueue<QPair<QString,QStringList>> *m_search_result_content = nullptr;
QQueue<QPair<QString, QStringList>> *m_search_result_content = nullptr;
bool m_searching = false;
};

View File

@ -25,12 +25,10 @@
#define NEW_QUEUE(a) a = new QQueue<QString>(); qDebug("---------------------------%s %s %s new at %d..",__FILE__,__FUNCTION__,#a,__LINE__);
//#define DELETE_QUEUE(a )
FirstIndex::FirstIndex()
{
FirstIndex::FirstIndex() {
}
FirstIndex::~FirstIndex()
{
FirstIndex::~FirstIndex() {
qDebug() << "~FirstIndex";
if(this->q_index)
delete this->q_index;
@ -38,38 +36,37 @@ FirstIndex::~FirstIndex()
if(this->q_content_index)
delete this->q_content_index;
this->q_content_index = nullptr;
if (this->p_indexGenerator)
if(this->p_indexGenerator)
delete this->p_indexGenerator;
this->p_indexGenerator = nullptr;
qDebug() << "~FirstIndex end";
}
void FirstIndex::DoSomething(const QFileInfo& fileInfo){
void FirstIndex::DoSomething(const QFileInfo& fileInfo) {
// qDebug() << "there are some shit here"<<fileInfo.fileName() << fileInfo.absoluteFilePath() << QString(fileInfo.isDir() ? "1" : "0");
this->q_index->enqueue(QVector<QString>() << fileInfo.fileName() << fileInfo.absoluteFilePath() << QString((fileInfo.isDir() && (!fileInfo.isSymLink())) ? "1" : "0"));
if ((fileInfo.fileName().split(".", QString::SkipEmptyParts).length() > 1) && (true == targetFileTypeMap[fileInfo.fileName().split(".").last()])){
if((fileInfo.fileName().split(".", QString::SkipEmptyParts).length() > 1) && (true == targetFileTypeMap[fileInfo.fileName().split(".").last()])) {
this->q_content_index->enqueue(fileInfo.absoluteFilePath());
}
}
void FirstIndex::run(){
void FirstIndex::run() {
QTime t1 = QTime::currentTime();
// Create a fifo at ~/.config/org.ukui/ukui-search, the fifo is used to control the order of child processes' running.
QDir fifoDir = QDir(QDir::homePath()+"/.config/org.ukui/ukui-search");
QDir fifoDir = QDir(QDir::homePath() + "/.config/org.ukui/ukui-search");
if(!fifoDir.exists())
qDebug()<<"create fifo path"<<fifoDir.mkpath(fifoDir.absolutePath());
qDebug() << "create fifo path" << fifoDir.mkpath(fifoDir.absolutePath());
unlink(UKUI_SEARCH_PIPE_PATH);
int retval = mkfifo(UKUI_SEARCH_PIPE_PATH, 0777);
if(retval == -1)
{
qCritical()<<"creat fifo error!!";
syslog(LOG_ERR,"creat fifo error!!\n");
if(retval == -1) {
qCritical() << "creat fifo error!!";
syslog(LOG_ERR, "creat fifo error!!\n");
assert(false);
return;
}
qDebug()<<"create fifo success\n";
qDebug() << "create fifo success\n";
QString indexDataBaseStatus = GlobalSettings::getInstance()->getValue(INDEX_DATABASE_STATE).toString();
QString contentIndexDataBaseStatus = GlobalSettings::getInstance()->getValue(CONTENT_INDEX_DATABASE_STATE).toString();
@ -80,16 +77,14 @@ void FirstIndex::run(){
qDebug() << "inotifyIndexStatus: " << inotifyIndexStatus;
/* || contentIndexDataBaseStatus == ""*/
if (indexDataBaseStatus == ""){
if(indexDataBaseStatus == "") {
this->bool_dataBaseExist = false;
}
else{
} else {
this->bool_dataBaseExist = true;
}
if (indexDataBaseStatus != "2" || contentIndexDataBaseStatus != "2" || inotifyIndexStatus != "2"){
if(indexDataBaseStatus != "2" || contentIndexDataBaseStatus != "2" || inotifyIndexStatus != "2") {
this->bool_dataBaseStatusOK = false;
}
else{
} else {
this->bool_dataBaseStatusOK = true;
}
@ -104,8 +99,7 @@ void FirstIndex::run(){
buffer[0] = 0x1;
buffer[1] = '\0';
fifo_fd = open(UKUI_SEARCH_PIPE_PATH, O_RDWR);
if(fifo_fd == -1)
{
if(fifo_fd == -1) {
perror("open fifo error\n");
assert(false);
}
@ -119,23 +113,20 @@ void FirstIndex::run(){
pid_t pid;
pid = fork();
if(pid == 0)
{
if(pid == 0) {
prctl(PR_SET_PDEATHSIG, SIGTERM);
prctl(PR_SET_NAME,"first-index");
if (this->bool_dataBaseExist){
if (this->bool_dataBaseStatusOK){
prctl(PR_SET_NAME, "first-index");
if(this->bool_dataBaseExist) {
if(this->bool_dataBaseStatusOK) {
::_exit(0);
}
else{
} else {
//if the parameter is false, index won't be rebuild
//if it is true, index will be rebuild
p_indexGenerator = IndexGenerator::getInstance(true,this);
p_indexGenerator = IndexGenerator::getInstance(true, this);
}
}
else{
} else {
// p_indexGenerator = IndexGenerator::getInstance(false,this);
p_indexGenerator = IndexGenerator::getInstance(true,this);
p_indexGenerator = IndexGenerator::getInstance(true, this);
}
QSemaphore sem(5);
@ -150,16 +141,16 @@ void FirstIndex::run(){
this->setPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
this->Traverse();
FileUtils::_max_index_count = this->q_index->length();
qDebug()<<"max_index_count:"<<FileUtils::_max_index_count;
qDebug() << "max_index_count:" << FileUtils::_max_index_count;
sem.release(5);
// });
QtConcurrent::run([&](){
QtConcurrent::run([&]() {
sem.acquire(2);
mutex2.unlock();
qDebug() << "index start;";
QQueue<QVector<QString>>* tmp = new QQueue<QVector<QString>>();
while (!this->q_index->empty()) {
for (size_t i = 0; (i < 8192) && (!this->q_index->empty()); ++i){
while(!this->q_index->empty()) {
for(size_t i = 0; (i < 8192) && (!this->q_index->empty()); ++i) {
tmp->enqueue(this->q_index->dequeue());
}
this->p_indexGenerator->creatAllIndex(tmp);
@ -170,14 +161,14 @@ void FirstIndex::run(){
qDebug() << "index end;";
sem.release(2);
});
QtConcurrent::run([&](){
QtConcurrent::run([&]() {
sem.acquire(2);
mutex3.unlock();
QQueue<QString>* tmp = new QQueue<QString>();
qDebug()<<"q_content_index:"<<q_content_index->size();
while (!this->q_content_index->empty()) {
qDebug() << "q_content_index:" << q_content_index->size();
while(!this->q_content_index->empty()) {
// for (size_t i = 0; (i < this->u_send_length) && (!this->q_content_index->empty()); ++i){
for (size_t i = 0; (i < 30) && (!this->q_content_index->empty()); ++i){
for(size_t i = 0; (i < 30) && (!this->q_content_index->empty()); ++i) {
tmp->enqueue(this->q_content_index->dequeue());
}
this->p_indexGenerator->creatAllIndex(tmp);
@ -195,33 +186,28 @@ void FirstIndex::run(){
mutex2.unlock();
mutex3.unlock();
if (this->q_index)
if(this->q_index)
delete this->q_index;
this->q_index = nullptr;
if (this->q_content_index)
if(this->q_content_index)
delete this->q_content_index;
this->q_content_index = nullptr;
if (p_indexGenerator)
if(p_indexGenerator)
delete p_indexGenerator;
p_indexGenerator = nullptr;
// GlobalSettings::getInstance()->forceSync();
::_exit(0);
}
else if(pid < 0)
{
qWarning()<<"First Index fork error!!";
}
else
{
waitpid(pid,NULL,0);
} else if(pid < 0) {
qWarning() << "First Index fork error!!";
} else {
waitpid(pid, NULL, 0);
--FileUtils::_index_status;
}
GlobalSettings::getInstance()->setValue(INOTIFY_NORMAL_EXIT, "2");
int retval1 = write(fifo_fd, buffer, strlen(buffer));
if(retval1 == -1)
{
if(retval1 == -1) {
qWarning("write error\n");
}
qDebug("write data ok!\n");

View File

@ -42,8 +42,7 @@
#include "inotify-index.h"
#include "file-utils.h"
class FirstIndex : public QThread, public Traverse_BFS
{
class FirstIndex : public QThread, public Traverse_BFS {
public:
FirstIndex();
~FirstIndex();

View File

@ -42,36 +42,32 @@ QList<Document> *_doc_list_path;
QMutex _mutex_doc_list_path;
QList<Document> *_doc_list_content;
QMutex _mutex_doc_list_content;
IndexGenerator *IndexGenerator::getInstance(bool rebuild, QObject *parent)
{
IndexGenerator *IndexGenerator::getInstance(bool rebuild, QObject *parent) {
QMutexLocker locker(&m_mutex);
if (!global_instance) {
qDebug()<<"IndexGenerator=================";
global_instance = new IndexGenerator(rebuild,parent);
if(!global_instance) {
qDebug() << "IndexGenerator=================";
global_instance = new IndexGenerator(rebuild, parent);
}
qDebug() << "global_instance" << global_instance;
qDebug() << "QThread::currentThreadId()" << QThread::currentThreadId();
return global_instance;
}
bool IndexGenerator::setIndexdataPath()
{
bool IndexGenerator::setIndexdataPath() {
return true;
}
//文件名索引
bool IndexGenerator::creatAllIndex(QQueue<QVector<QString> > *messageList)
{
bool IndexGenerator::creatAllIndex(QQueue<QVector<QString> > *messageList) {
// FileUtils::_index_status |= 0x1;
// qDebug() << messageList->size();
HandlePathList(messageList);
if (_doc_list_path == NULL){
if(_doc_list_path == NULL) {
return false;
}
qDebug()<<"begin creatAllIndex";
GlobalSettings::getInstance()->setValue(INDEX_DATABASE_STATE,"0");
try
{
qDebug() << "begin creatAllIndex";
GlobalSettings::getInstance()->setValue(INDEX_DATABASE_STATE, "0");
try {
// m_indexer = new Xapian::TermGenerator();
// m_indexer.set_database(*m_database_path);
//可以实现拼写纠正
@ -80,7 +76,7 @@ bool IndexGenerator::creatAllIndex(QQueue<QVector<QString> > *messageList)
// int count =0;
for (auto i : *_doc_list_path){
for(auto i : *_doc_list_path) {
insertIntoDatabase(i);
// if(++count > 8999){
@ -89,17 +85,15 @@ bool IndexGenerator::creatAllIndex(QQueue<QVector<QString> > *messageList)
// }
}
m_database_path->commit();
}
catch(const Xapian::Error &e)
{
qWarning()<<"creatAllIndex fail!"<<QString::fromStdString(e.get_description());
} catch(const Xapian::Error &e) {
qWarning() << "creatAllIndex fail!" << QString::fromStdString(e.get_description());
//need a record
GlobalSettings::getInstance()->setValue(INDEX_DATABASE_STATE,"1");
GlobalSettings::getInstance()->setValue(INDEX_DATABASE_STATE, "1");
// FileUtils::_index_status &= ~0x1;
assert(false);
}
GlobalSettings::getInstance()->setValue(INDEX_DATABASE_STATE,"2");
qDebug()<<"finish creatAllIndex";
GlobalSettings::getInstance()->setValue(INDEX_DATABASE_STATE, "2");
qDebug() << "finish creatAllIndex";
// FileUtils::_index_status &= ~0x1;
_doc_list_path->clear();
delete _doc_list_path;
@ -107,41 +101,36 @@ bool IndexGenerator::creatAllIndex(QQueue<QVector<QString> > *messageList)
return true;
}
//文件内容索引
bool IndexGenerator::creatAllIndex(QQueue<QString> *messageList)
{
bool IndexGenerator::creatAllIndex(QQueue<QString> *messageList) {
// FileUtils::_index_status |= 0x2;
HandlePathList(messageList);
qDebug()<<"begin creatAllIndex for content";
if (_doc_list_content == NULL){
qDebug() << "begin creatAllIndex for content";
if(_doc_list_content == NULL) {
return false;
}
int size = _doc_list_content->size();
qDebug()<<"begin creatAllIndex for content"<<size;
if(!size == 0)
{
GlobalSettings::getInstance()->setValue(CONTENT_INDEX_DATABASE_STATE,"0");
try
{
int count =0;
for (auto i : *_doc_list_content){
qDebug() << "begin creatAllIndex for content" << size;
if(!size == 0) {
GlobalSettings::getInstance()->setValue(CONTENT_INDEX_DATABASE_STATE, "0");
try {
int count = 0;
for(auto i : *_doc_list_content) {
insertIntoContentDatabase(i);
if(++count > 999){
if(++count > 999) {
count = 0;
m_database_content->commit();
}
}
}
m_database_content->commit();
}
catch(const Xapian::Error &e)
{
qWarning()<<"creat content Index fail!"<<QString::fromStdString(e.get_description());
GlobalSettings::getInstance()->setValue(CONTENT_INDEX_DATABASE_STATE,"1");
} catch(const Xapian::Error &e) {
qWarning() << "creat content Index fail!" << QString::fromStdString(e.get_description());
GlobalSettings::getInstance()->setValue(CONTENT_INDEX_DATABASE_STATE, "1");
// FileUtils::_index_status &= ~0x2;
assert(false);
}
GlobalSettings::getInstance()->setValue(CONTENT_INDEX_DATABASE_STATE,"2");
GlobalSettings::getInstance()->setValue(CONTENT_INDEX_DATABASE_STATE, "2");
// FileUtils::_index_status &= ~0x2;
qDebug()<<"finish creatAllIndex for content";
qDebug() << "finish creatAllIndex for content";
_doc_list_content->clear();
delete _doc_list_content;
_doc_list_content = nullptr;
@ -151,36 +140,28 @@ bool IndexGenerator::creatAllIndex(QQueue<QString> *messageList)
}
IndexGenerator::IndexGenerator(bool rebuild, QObject *parent) : QObject(parent)
{
IndexGenerator::IndexGenerator(bool rebuild, QObject *parent) : QObject(parent) {
QDir database(QString::fromStdString(INDEX_PATH));
if(database.exists())
{
if(database.exists()) {
if(rebuild)
qDebug()<<"remove"<<database.removeRecursively();
}
else
{
qDebug()<<"create index path"<<database.mkpath(QString::fromStdString(INDEX_PATH));
qDebug() << "remove" << database.removeRecursively();
} else {
qDebug() << "create index path" << database.mkpath(QString::fromStdString(INDEX_PATH));
}
database.setPath(QString::fromStdString(CONTENT_INDEX_PATH));
if(database.exists())
{
if(database.exists()) {
if(rebuild)
qDebug()<<"remove"<<database.removeRecursively();
}
else
{
qDebug()<<"create content index path"<<database.mkpath(QString::fromStdString(CONTENT_INDEX_PATH));
qDebug() << "remove" << database.removeRecursively();
} else {
qDebug() << "create content index path" << database.mkpath(QString::fromStdString(CONTENT_INDEX_PATH));
}
m_database_path = new Xapian::WritableDatabase(INDEX_PATH, Xapian::DB_CREATE_OR_OPEN);
m_database_content = new Xapian::WritableDatabase(CONTENT_INDEX_PATH, Xapian::DB_CREATE_OR_OPEN);
}
IndexGenerator::~IndexGenerator()
{
IndexGenerator::~IndexGenerator() {
QMutexLocker locker(&m_mutex);
qDebug() << "~IndexGenerator";
if(m_database_path)
@ -216,8 +197,7 @@ IndexGenerator::~IndexGenerator()
qDebug() << "~IndexGenerator end";
}
void IndexGenerator::insertIntoDatabase(Document& doc)
{
void IndexGenerator::insertIntoDatabase(Document& doc) {
// qDebug()<< "--index start--";
Xapian::Document document = doc.getXapianDocument();
// m_indexer.set_document(document);
@ -229,24 +209,22 @@ void IndexGenerator::insertIntoDatabase(Document& doc)
// qDebug()<<"insert m_database_path:"<<QString::fromStdString(document.get_data());
// qDebug()<<"document:"<<QString::fromStdString(document.get_description());
Xapian::docid innerId= m_database_path->replace_document(doc.getUniqueTerm(),document);
Xapian::docid innerId = m_database_path->replace_document(doc.getUniqueTerm(), document);
// qDebug()<<"replace doc docid="<<static_cast<int>(innerId);
// qDebug()<< "--index finish--";
return;
}
//#define fun(a) a=new ;printf()
void IndexGenerator::insertIntoContentDatabase(Document& doc)
{
Xapian::docid innerId= m_database_content->replace_document(doc.getUniqueTerm(),doc.getXapianDocument());
void IndexGenerator::insertIntoContentDatabase(Document& doc) {
Xapian::docid innerId = m_database_content->replace_document(doc.getUniqueTerm(), doc.getXapianDocument());
// qDebug()<<"replace doc docid="<<static_cast<int>(innerId);
// qDebug()<< "--index finish--";
return;
}
void IndexGenerator::HandlePathList(QQueue<QVector<QString>> *messageList)
{
qDebug()<<"Begin HandlePathList!";
qDebug()<<messageList->size();
void IndexGenerator::HandlePathList(QQueue<QVector<QString>> *messageList) {
qDebug() << "Begin HandlePathList!";
qDebug() << messageList->size();
// qDebug()<<QString::number(quintptr(QThread::currentThreadId()));
// QFuture<Document> future = QtConcurrent::mapped(*messageList,&IndexGenerator::GenerateDocument);
@ -259,12 +237,11 @@ void IndexGenerator::HandlePathList(QQueue<QVector<QString>> *messageList)
pool.setMaxThreadCount(((QThread::idealThreadCount() - 1) / 2) + 1);
pool.setExpiryTimeout(100);
ConstructDocumentForPath *constructer;
while(!messageList->isEmpty())
{
constructer = new ConstructDocumentForPath(messageList->dequeue());
pool.start(constructer);
while(!messageList->isEmpty()) {
constructer = new ConstructDocumentForPath(messageList->dequeue());
pool.start(constructer);
}
qDebug()<<"pool finish"<<pool.waitForDone(-1);
qDebug() << "pool finish" << pool.waitForDone(-1);
// if(constructer)
// delete constructer;
// constructer = nullptr;
@ -276,14 +253,13 @@ void IndexGenerator::HandlePathList(QQueue<QVector<QString>> *messageList)
// m_doc_list_path = std::move(future.results());
// qDebug()<<m_doc_list_path.size();
qDebug()<<"Finish HandlePathList!";
qDebug() << "Finish HandlePathList!";
return;
}
void IndexGenerator::HandlePathList(QQueue<QString> *messageList)
{
qDebug()<<"Begin HandlePathList for content index!";
qDebug()<<messageList->size();
void IndexGenerator::HandlePathList(QQueue<QString> *messageList) {
qDebug() << "Begin HandlePathList for content index!";
qDebug() << messageList->size();
// qDebug()<<QString::number(quintptr(QThread::currentThreadId()));
ChineseSegmentation::getInstance();
ConstructDocumentForContent *constructer;
@ -291,12 +267,11 @@ void IndexGenerator::HandlePathList(QQueue<QString> *messageList)
// pool.setMaxThreadCount(((QThread::idealThreadCount() - 1) / 2) + 1);
pool.setMaxThreadCount(1);
pool.setExpiryTimeout(100);
while(!messageList->isEmpty())
{
constructer = new ConstructDocumentForContent(messageList->dequeue());
pool.start(constructer);
while(!messageList->isEmpty()) {
constructer = new ConstructDocumentForContent(messageList->dequeue());
pool.start(constructer);
}
qDebug()<<"pool finish"<<pool.waitForDone(-1);
qDebug() << "pool finish" << pool.waitForDone(-1);
// if(constructer)
// delete constructer;
// constructer = nullptr;
@ -316,19 +291,18 @@ void IndexGenerator::HandlePathList(QQueue<QString> *messageList)
// m_doc_list_content = std::move(future.results());
// future.cancel();
qDebug()<<"Finish HandlePathList for content index!";
qDebug() << "Finish HandlePathList for content index!";
return;
}
Document IndexGenerator::GenerateDocument(const QVector<QString> &list)
{
Document IndexGenerator::GenerateDocument(const QVector<QString> &list) {
Document doc;
// qDebug()<<QString::number(quintptr(QThread::currentThreadId()));
//0-filename 1-filepathname 2-file or dir
QString index_text = list.at(0);
QString sourcePath = list.at(1);
index_text = index_text.replace(""," ");
QString sourcePath = list.at(1);
index_text = index_text.replace("", " ");
index_text = index_text.simplified();
//不带多音字版
@ -336,16 +310,16 @@ Document IndexGenerator::GenerateDocument(const QVector<QString> &list)
//多音字版
//现加入首字母
QStringList pinyin_text_list = FileUtils::findMultiToneWords(QString(list.at(0)).replace(".",""));
for (QString& i : pinyin_text_list){
QStringList pinyin_text_list = FileUtils::findMultiToneWords(QString(list.at(0)).replace(".", ""));
for(QString& i : pinyin_text_list) {
i.replace("", " ");
i = i.simplified();
}
QString uniqueterm = QString::fromStdString(FileUtils::makeDocUterm(sourcePath));
QString upTerm = QString::fromStdString(FileUtils::makeDocUterm(sourcePath.section("/",0,-2,QString::SectionIncludeLeadingSep)));
QString upTerm = QString::fromStdString(FileUtils::makeDocUterm(sourcePath.section("/", 0, -2, QString::SectionIncludeLeadingSep)));
// QString uniqueterm1 = QString::fromStdString(QCryptographicHash::hash(sourcePath.toUtf8(),QCryptographicHash::Md5).toStdString());
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
//QByteArray 和 QString 之间会进行隐式转换,造成字符串被截断等意想不到的后果!!!!!!! zpf
// if(uniqueterm1!=uniqueterm){
// qDebug()<<"-----------------------------------------start";
@ -353,7 +327,7 @@ Document IndexGenerator::GenerateDocument(const QVector<QString> &list)
// qDebug()<<uniqueterm;
// qDebug()<<"------------------------------------------finish";
// }
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
doc.setData(sourcePath);
doc.setUniqueTerm(uniqueterm);
@ -367,8 +341,7 @@ Document IndexGenerator::GenerateDocument(const QVector<QString> &list)
}
Document IndexGenerator::GenerateContentDocument(const QString &path)
{
Document IndexGenerator::GenerateContentDocument(const QString &path) {
// 构造文本索引的document
QString content;
QStringList tmp;
@ -377,7 +350,7 @@ Document IndexGenerator::GenerateContentDocument(const QString &path)
Document doc;
QString uniqueterm;
QString upTerm;
FileReader::getTextContent(path,content);
FileReader::getTextContent(path, content);
term = ChineseSegmentation::getInstance()->callSegement(content);
// QStringList term = content.split("");
@ -386,9 +359,8 @@ Document IndexGenerator::GenerateContentDocument(const QString &path)
doc.setUniqueTerm(uniqueterm);
doc.addTerm(upTerm);
doc.addValue(path);
for(int i = 0;i<term.size();++i)
{
doc.addPosting(term.at(i).word,term.at(i).offsets,static_cast<int>(term.at(i).weight));
for(int i = 0; i < term.size(); ++i) {
doc.addPosting(term.at(i).word, term.at(i).offsets, static_cast<int>(term.at(i).weight));
}
@ -408,8 +380,7 @@ Document IndexGenerator::GenerateContentDocument(const QString &path)
return doc;
}
bool IndexGenerator::isIndexdataExist()
{
bool IndexGenerator::isIndexdataExist() {
// Xapian::Database db(m_index_data_path->toStdString());
return true;
@ -417,12 +388,10 @@ bool IndexGenerator::isIndexdataExist()
}
QStringList IndexGenerator::IndexSearch(QString indexText)
{
QStringList IndexGenerator::IndexSearch(QString indexText) {
QStringList searchResult;
try
{
qDebug()<<"--search start--";
try {
qDebug() << "--search start--";
Xapian::Database db(INDEX_PATH);
Xapian::Enquire enquire(db);
@ -431,33 +400,32 @@ QStringList IndexGenerator::IndexSearch(QString indexText)
qp.set_database(db);
auto userInput = indexText;
std::string queryStr = indexText.replace(""," ").toStdString();
std::string queryStr = indexText.replace("", " ").toStdString();
// std::string s =db.get_spelling_suggestion(queryStr,10);
// qDebug()<<"spelling_suggestion!"<<QString::fromStdString(s);
qDebug()<<"queryStr!"<<QString::fromStdString(queryStr);
qDebug() << "queryStr!" << QString::fromStdString(queryStr);
//Creat a query
Xapian::Query queryPhrase = qp.parse_query(queryStr,Xapian::QueryParser::FLAG_PHRASE);
Xapian::Query queryPhrase = qp.parse_query(queryStr, Xapian::QueryParser::FLAG_PHRASE);
std::vector<Xapian::Query> v;
for(int i=0;i<userInput.size();i++)
{
for(int i = 0; i < userInput.size(); i++) {
v.push_back(Xapian::Query(QString(userInput.at(i)).toStdString()));
qDebug()<<userInput.at(i);
qDebug()<<QString::fromStdString(Xapian::Query(QString(userInput.at(i)).toStdString()).get_description());
qDebug() << userInput.at(i);
qDebug() << QString::fromStdString(Xapian::Query(QString(userInput.at(i)).toStdString()).get_description());
}
Xapian::Query queryNear =Xapian::Query(Xapian::Query::OP_NEAR, v.begin(), v.end());
Xapian::Query query = Xapian::Query(Xapian::Query::OP_AND,queryNear,queryPhrase);
Xapian::Query queryNear = Xapian::Query(Xapian::Query::OP_NEAR, v.begin(), v.end());
Xapian::Query query = Xapian::Query(Xapian::Query::OP_AND, queryNear, queryPhrase);
qDebug()<<QString::fromStdString(query.get_description());
qDebug() << QString::fromStdString(query.get_description());
enquire.set_query(query);
Xapian::MSet result = enquire.get_mset(0, 9999);
qDebug()<< "find results count=" <<static_cast<int>(result.get_matches_estimated());
qDebug() << "find results count=" << static_cast<int>(result.get_matches_estimated());
// QStringList *pathTobeDelete = new QStringList;
//get search result
for (auto it = result.begin(); it != result.end(); ++it) {
for(auto it = result.begin(); it != result.end(); ++it) {
Xapian::Document doc = it.get_document();
std::string data = doc.get_data();
Xapian::weight docScoreWeight = it.get_weight();
@ -465,27 +433,22 @@ QStringList IndexGenerator::IndexSearch(QString indexText)
// QFileInfo *info = new QFileInfo(QString::fromStdString(data));
QFileInfo info(QString::fromStdString(data));
if(!info.exists())
{
if(!info.exists()) {
// pathTobeDelete->append(QString::fromStdString(data));
qDebug()<<QString::fromStdString(data)<<"is not exist!!";
}
else
{
qDebug() << QString::fromStdString(data) << "is not exist!!";
} else {
searchResult.append(QString::fromStdString(data));
}
qDebug()<< "doc="<< QString::fromStdString(data) << ",weight=" <<docScoreWeight << ",percent=" << docScorePercent;
qDebug() << "doc=" << QString::fromStdString(data) << ",weight=" << docScoreWeight << ",percent=" << docScorePercent;
}
// //Delete those path doc which is not already exist.
// if(!pathTobeDelete->isEmpty())
// deleteAllIndex(pathTobeDelete);
qDebug()<< "--search finish--";
}
catch(const Xapian::Error &e)
{
qDebug() <<QString::fromStdString(e.get_description());
qDebug() << "--search finish--";
} catch(const Xapian::Error &e) {
qDebug() << QString::fromStdString(e.get_description());
}
return searchResult;
}
@ -555,32 +518,27 @@ QStringList IndexGenerator::IndexSearch(QString indexText)
// }
//}
bool IndexGenerator::deleteAllIndex(QStringList *pathlist)
{
bool IndexGenerator::deleteAllIndex(QStringList *pathlist) {
QStringList *list = pathlist;
if(list->isEmpty())
return true;
for(int i = 0;i<list->size();i++)
{
for(int i = 0; i < list->size(); i++) {
QString doc = list->at(i);
std::string uniqueterm = FileUtils::makeDocUterm(doc);
try
{
qDebug()<<"--delete start--";
try {
qDebug() << "--delete start--";
m_database_path->delete_document(uniqueterm);
m_database_content->delete_document(uniqueterm);
qDebug()<<"delete path"<<doc;
qDebug()<<"delete md5"<<QString::fromStdString(uniqueterm);
qDebug() << "delete path" << doc;
qDebug() << "delete md5" << QString::fromStdString(uniqueterm);
m_database_path->commit();
m_database_content->commit();
qDebug()<< "--delete finish--";
qDebug() << "--delete finish--";
// qDebug()<<"m_database_path->get_lastdocid()!!!"<<m_database_path->get_lastdocid();
// qDebug()<<"m_database_path->get_doccount()!!!"<<m_database_path->get_doccount();
}
catch(const Xapian::Error &e)
{
qWarning()<<QString::fromStdString(e.get_description());
} catch(const Xapian::Error &e) {
qWarning() << QString::fromStdString(e.get_description());
return false;
}
}

View File

@ -37,11 +37,10 @@ extern QMutex _mutex_doc_list_path;
extern QList<Document> *_doc_list_content;
extern QMutex _mutex_doc_list_content;
class IndexGenerator : public QObject
{
class IndexGenerator : public QObject {
Q_OBJECT
public:
static IndexGenerator *getInstance(bool rebuild = false,QObject *parent = nullptr);
static IndexGenerator *getInstance(bool rebuild = false, QObject *parent = nullptr);
~IndexGenerator();
bool setIndexdataPath();
bool isIndexdataExist();
@ -58,7 +57,7 @@ public Q_SLOTS:
bool deleteAllIndex(QStringList *pathlist);
private:
explicit IndexGenerator(bool rebuild = false,QObject *parent = nullptr);
explicit IndexGenerator(bool rebuild = false, QObject *parent = nullptr);
static QMutex m_mutex;
//For file name index
void HandlePathList(QQueue<QVector<QString> > *messageList);
@ -72,7 +71,7 @@ private:
// QList<Document> *m_doc_list_path; //for path index
// QList<Document> *m_doc_list_content; // for text content index
QMap<QString,QStringList> m_index_map;
QMap<QString, QStringList> m_index_map;
QString m_index_data_path;
Xapian::WritableDatabase* m_database_path;
Xapian::WritableDatabase* m_database_content;

View File

@ -46,8 +46,7 @@
CREATE_FILE_NAME_INDEX \
CREATE_FILE_CONTENT_INDEX
InotifyIndex::InotifyIndex(const QString& path) : Traverse_BFS(path)
{
InotifyIndex::InotifyIndex(const QString& path) : Traverse_BFS(path) {
qDebug() << "setInotifyMaxUserWatches start";
UkuiSearchQDBus usQDBus;
usQDBus.setInotifyMaxUserWatches();
@ -55,24 +54,23 @@ InotifyIndex::InotifyIndex(const QString& path) : Traverse_BFS(path)
}
InotifyIndex::~InotifyIndex()
{
InotifyIndex::~InotifyIndex() {
IndexGenerator::getInstance()->~IndexGenerator();
qWarning() << "~InotifyIndex";
}
void InotifyIndex::firstTraverse(){
void InotifyIndex::firstTraverse() {
QQueue<QString> bfs;
bfs.enqueue(this->path);
QFileInfoList list;
QDir dir;
dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
dir.setSorting(QDir::DirsFirst);
while (!bfs.empty()) {
while(!bfs.empty()) {
dir.setPath(bfs.dequeue());
list = dir.entryInfoList();
for (auto i : list){
if (i.isDir() && (!(i.isSymLink()))){
for(auto i : list) {
if(i.isDir() && (!(i.isSymLink()))) {
this->AddWatch(i.absoluteFilePath());
bfs.enqueue(i.absoluteFilePath());
}
@ -80,24 +78,24 @@ void InotifyIndex::firstTraverse(){
}
}
void InotifyIndex::DoSomething(const QFileInfo& fileInfo){
void InotifyIndex::DoSomething(const QFileInfo& fileInfo) {
qDebug() << fileInfo.fileName() << "-------" << fileInfo.absoluteFilePath();
if(fileInfo.isDir() && (!fileInfo.isSymLink())){
if(fileInfo.isDir() && (!fileInfo.isSymLink())) {
this->AddWatch(fileInfo.absoluteFilePath());
}
QQueue<QVector<QString> > tempFile;
tempFile.enqueue(QVector<QString>() << fileInfo.fileName() << fileInfo.absoluteFilePath() << QString((fileInfo.isDir() && (!fileInfo.isSymLink())) ? "1" : "0"));
IndexGenerator::getInstance()->creatAllIndex(&tempFile);
if ((fileInfo.fileName().split(".", QString::SkipEmptyParts).length() > 1) && (true == targetFileTypeMap[fileInfo.fileName().split(".").last()])){
if((fileInfo.fileName().split(".", QString::SkipEmptyParts).length() > 1) && (true == targetFileTypeMap[fileInfo.fileName().split(".").last()])) {
QQueue<QString> tmp;
tmp.enqueue(fileInfo.absoluteFilePath());
IndexGenerator::getInstance()->creatAllIndex(&tmp);
}
}
bool InotifyIndex::AddWatch(const QString &path){
bool InotifyIndex::AddWatch(const QString &path) {
int ret = inotify_add_watch(m_fd, path.toStdString().c_str(), (IN_MOVED_FROM | IN_MOVED_TO | IN_CREATE | IN_DELETE | IN_MODIFY));
if (ret == -1) {
if(ret == -1) {
qDebug() << "AddWatch error:" << path;
return false;
}
@ -108,67 +106,63 @@ bool InotifyIndex::AddWatch(const QString &path){
return true;
}
bool InotifyIndex::RemoveWatch(const QString &path, bool removeFromDatabase){
bool InotifyIndex::RemoveWatch(const QString &path, bool removeFromDatabase) {
int ret = inotify_rm_watch(m_fd, currentPath.key(path));
if (ret){
if(ret) {
qDebug() << "remove path error";
return false;
}
// Q_ASSERT(ret == 0);
assert(ret == 0);
if (removeFromDatabase) {
for (QMap<int, QString>::Iterator i = currentPath.begin(); i != currentPath.end();) {
// qDebug() << i.value();
if (i.value().length() > path.length()){
// if (i.value().mid(0, path.length()) == path){
// if (path.startsWith(i.value())){
if (i.value().startsWith(path)){
if(removeFromDatabase) {
for(QMap<int, QString>::Iterator i = currentPath.begin(); i != currentPath.end();) {
// qDebug() << i.value();
if(i.value().length() > path.length()) {
// if (i.value().mid(0, path.length()) == path){
// if (path.startsWith(i.value())){
if(i.value().startsWith(path)) {
qDebug() << "remove path: " << i.value();
ret = inotify_rm_watch(m_fd, currentPath.key(path));
if (ret){
if(ret) {
qDebug() << "remove path error";
// return false;
// return false;
}
// assert(ret == 0);
// assert(ret == 0);
/*--------------------------------*/
//在此调用删除索引
qDebug() << i.value();
IndexGenerator::getInstance()->deleteAllIndex(new QStringList(i.value()));
/*--------------------------------*/
currentPath.erase(i++);
// i++;
}
else{
// i++;
} else {
i++;
}
}
else{
} else {
i++;
}
}
} else {
for (QMap<int, QString>::Iterator i = currentPath.begin(); i != currentPath.end();) {
// qDebug() << i.value();
if (i.value().length() > path.length()){
// if (i.value().mid(0, path.length()) == path){
// if (path.startsWith(i.value())){
if (i.value().startsWith(path)){
for(QMap<int, QString>::Iterator i = currentPath.begin(); i != currentPath.end();) {
// qDebug() << i.value();
if(i.value().length() > path.length()) {
// if (i.value().mid(0, path.length()) == path){
// if (path.startsWith(i.value())){
if(i.value().startsWith(path)) {
qDebug() << "remove path: " << i.value();
ret = inotify_rm_watch(m_fd, currentPath.key(path));
if (ret){
if(ret) {
qDebug() << "remove path error";
// return false;
// return false;
}
// assert(ret == 0);
// assert(ret == 0);
currentPath.erase(i++);
// i++;
}
else{
// i++;
} else {
i++;
}
}
else{
} else {
i++;
}
}
@ -179,7 +173,7 @@ bool InotifyIndex::RemoveWatch(const QString &path, bool removeFromDatabase){
return true;
}
void InotifyIndex::eventProcess(const char* buf, ssize_t tmp){
void InotifyIndex::eventProcess(const char* buf, ssize_t tmp) {
QQueue<QVector<QString>>* indexQueue = new QQueue<QVector<QString>>();
QQueue<QString>* contentIndexQueue = new QQueue<QString>();
@ -187,27 +181,27 @@ void InotifyIndex::eventProcess(const char* buf, ssize_t tmp){
numRead = tmp;
char * p = const_cast<char*>(buf);
for (; p < buf + numRead;) {
for(; p < buf + numRead;) {
struct inotify_event * event = reinterpret_cast<inotify_event *>(p);
qDebug() << "Read Event event->wd: " << event->wd;
qDebug() << "Read Event: " << currentPath[event->wd] << QString(event->name) << event->cookie << event->wd << event->mask;
if(event->name[0] != '.'){
if(event->name[0] != '.') {
qDebug() << QString(currentPath[event->wd] + '/' + event->name);
// switch (event->mask) {
if (event->mask & IN_CREATE){
if(event->mask & IN_CREATE) {
//Create top dir first, traverse it last.
qDebug() << "IN_CREATE";
CREATE_FILE
if (event->mask & IN_ISDIR){
if(event->mask & IN_ISDIR) {
TRAVERSE_DIR
}
goto next;
}
if ((event->mask & IN_DELETE) | (event->mask & IN_MOVED_FROM)){
if((event->mask & IN_DELETE) | (event->mask & IN_MOVED_FROM)) {
qDebug() << "IN_DELETE or IN_MOVED_FROM";
if (event->mask & IN_ISDIR){
if(event->mask & IN_ISDIR) {
RemoveWatch(currentPath[event->wd] + '/' + event->name);
}
//delete once more
@ -215,24 +209,23 @@ void InotifyIndex::eventProcess(const char* buf, ssize_t tmp){
goto next;
}
if (event->mask & IN_MODIFY){
if(event->mask & IN_MODIFY) {
qDebug() << "IN_MODIFY";
if (!(event->mask & IN_ISDIR)){
if(!(event->mask & IN_ISDIR)) {
// IndexGenerator::getInstance()->deleteAllIndex(new QStringList(currentPath[event->wd] + '/' + event->name));
CREATE_FILE
}
goto next;
}
if (event->mask & IN_MOVED_TO){
if(event->mask & IN_MOVED_TO) {
qDebug() << "IN_MOVED_TO";
if (event->mask & IN_ISDIR){
if(event->mask & IN_ISDIR) {
RemoveWatch(currentPath[event->wd] + '/' + event->name);
// IndexGenerator::getInstance()->deleteAllIndex(new QStringList(currentPath[event->wd] + '/' + event->name));
CREATE_FILE
TRAVERSE_DIR
}
else {
} else {
IndexGenerator::getInstance()->deleteAllIndex(new QStringList(currentPath[event->wd] + '/' + event->name));
CREATE_FILE
}
@ -249,9 +242,9 @@ next:
contentIndexQueue = nullptr;
}
void InotifyIndex::run(){
void InotifyIndex::run() {
m_fd = inotify_init();
qDebug() << "m_fd----------->" <<m_fd;
qDebug() << "m_fd----------->" << m_fd;
this->AddWatch(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
this->setPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
@ -261,14 +254,12 @@ void InotifyIndex::run(){
char buffer[2];
memset(buffer, 0, sizeof(buffer));
fifo_fd = open(UKUI_SEARCH_PIPE_PATH, O_RDWR);
if(fifo_fd == -1)
{
if(fifo_fd == -1) {
perror("open fifo error\n");
assert(false);
}
int retval = read(fifo_fd, buffer, sizeof(buffer));
if(retval == -1)
{
if(retval == -1) {
perror("read error\n");
assert(false);
}
@ -276,7 +267,7 @@ void InotifyIndex::run(){
printf("read data ok\n");
close(fifo_fd);
if (buffer[0] & 0x1){
if(buffer[0] & 0x1) {
printf("data confirmed\n");
}
unlink(UKUI_SEARCH_PIPE_PATH);
@ -285,12 +276,12 @@ void InotifyIndex::run(){
ssize_t numRead;
while (FileUtils::SearchMethod::INDEXSEARCH == FileUtils::searchMethod) {
while(FileUtils::SearchMethod::INDEXSEARCH == FileUtils::searchMethod) {
// for (;;) { /* Read events forever */
memset(buf, 0x00, BUF_LEN);
numRead = read(m_fd, buf, BUF_LEN);
if (numRead == -1){
if(numRead == -1) {
printf("\033[1;31;40mread event error\033[0m\n");
GlobalSettings::getInstance()->setValue(INOTIFY_NORMAL_EXIT, "1");
fflush(stdout);
@ -300,16 +291,16 @@ void InotifyIndex::run(){
char * tmp = const_cast<char*>(buf);
for (; tmp < buf + numRead;) {
for(; tmp < buf + numRead;) {
struct inotify_event * event = reinterpret_cast<inotify_event *>(tmp);
// qDebug() << "Read Event: " << currentPath[event->wd] << QString(event->name) << event->cookie << event->wd << event->mask;
if(event->name[0] != '.'){
// qDebug() << "Read Event: " << currentPath[event->wd] << QString(event->name) << event->cookie << event->wd << event->mask;
if(event->name[0] != '.') {
GlobalSettings::getInstance()->setValue(INOTIFY_NORMAL_EXIT, "0");
break;
}
tmp += sizeof(struct inotify_event) + event->len;
}
if (tmp >= buf + numRead) {
if(tmp >= buf + numRead) {
continue;
}
@ -317,14 +308,13 @@ void InotifyIndex::run(){
pid_t pid;
pid = fork();
if(pid == 0)
{
if(pid == 0) {
prctl(PR_SET_PDEATHSIG, SIGTERM);
prctl(PR_SET_NAME,"inotify-index");
if (numRead == 0) {
prctl(PR_SET_NAME, "inotify-index");
if(numRead == 0) {
qDebug() << "read() from inotify fd returned 0!";
}
if (numRead == -1) {
if(numRead == -1) {
qDebug() << "read";
}
eventProcess(buf, numRead);
@ -336,29 +326,27 @@ void InotifyIndex::run(){
read_timeout->tv_sec = 40;
read_timeout->tv_usec = 0;
for(;;)
{
for(;;) {
FD_ZERO(&read_fds);
FD_SET(m_fd, &read_fds);
qDebug() << read_timeout->tv_sec;
rc = select(m_fd + 1, &read_fds, NULL, NULL, read_timeout);
if ( rc < 0 ) {
if(rc < 0) {
// error
qWarning() << "select result < 0, error!";
GlobalSettings::getInstance()->setValue(INOTIFY_NORMAL_EXIT, "1");
assert(false);
}
else if ( rc == 0 ) {
} else if(rc == 0) {
qDebug() << "select timeout!";
::free(read_timeout);
IndexGenerator::getInstance()->~IndexGenerator();
// GlobalSettings::getInstance()->forceSync();
::_exit(0);
}else{
::_exit(0);
} else {
GlobalSettings::getInstance()->setValue(INOTIFY_NORMAL_EXIT, "0");
memset(buf, 0x00, BUF_LEN);
numRead = read(m_fd, buf, BUF_LEN);
if (numRead == -1){
if(numRead == -1) {
printf("\033[1;31;40mread event error\033[0m\n");
fflush(stdout);
assert(false);
@ -368,18 +356,16 @@ void InotifyIndex::run(){
GlobalSettings::getInstance()->setValue(INOTIFY_NORMAL_EXIT, "2");
}
}
}
else if (pid > 0){
} else if(pid > 0) {
memset(buf, 0x00, BUF_LEN);
waitpid(pid, NULL, 0);
--FileUtils::_index_status;
}
else{
} else {
assert(false);
}
}
if (FileUtils::SearchMethod::DIRECTSEARCH == FileUtils::searchMethod) {
if(FileUtils::SearchMethod::DIRECTSEARCH == FileUtils::searchMethod) {
GlobalSettings::getInstance()->setValue(INOTIFY_NORMAL_EXIT, "3");
RemoveWatch(QStandardPaths::writableLocation(QStandardPaths::HomeLocation), false);
}

View File

@ -34,12 +34,11 @@
#define BUF_LEN 1024000
class InotifyIndex;
static InotifyIndex* global_instance_of_index = nullptr;
class InotifyIndex : public QThread, public Traverse_BFS
{
class InotifyIndex : public QThread, public Traverse_BFS {
Q_OBJECT
public:
static InotifyIndex* getInstance(const QString& path){
if (!global_instance_of_index) {
static InotifyIndex* getInstance(const QString& path) {
if(!global_instance_of_index) {
global_instance_of_index = new InotifyIndex(path);
}
return global_instance_of_index;

View File

@ -25,18 +25,15 @@ size_t SearchManager::uniqueSymbol3 = 0;
QMutex SearchManager::m_mutex1;
QMutex SearchManager::m_mutex2;
QMutex SearchManager::m_mutex3;
SearchManager::SearchManager(QObject *parent) : QObject(parent)
{
SearchManager::SearchManager(QObject *parent) : QObject(parent) {
m_pool.setMaxThreadCount(2);
m_pool.setExpiryTimeout(1000);
}
SearchManager::~SearchManager()
{
SearchManager::~SearchManager() {
}
int SearchManager::getCurrentIndexCount()
{
int SearchManager::getCurrentIndexCount() {
try {
Xapian::Database db(INDEX_PATH);
return db.get_doccount();
@ -46,9 +43,8 @@ int SearchManager::getCurrentIndexCount()
}
}
void SearchManager::onKeywordSearch(QString keyword,QQueue<QString> *searchResultFile,QQueue<QString> *searchResultDir,
QQueue<QPair<QString,QStringList>> *searchResultContent)
{
void SearchManager::onKeywordSearch(QString keyword, QQueue<QString> *searchResultFile, QQueue<QString> *searchResultDir,
QQueue<QPair<QString, QStringList>> *searchResultContent) {
m_mutex1.lock();
++uniqueSymbol1;
m_mutex1.unlock();
@ -59,21 +55,21 @@ void SearchManager::onKeywordSearch(QString keyword,QQueue<QString> *searchResul
++uniqueSymbol3;
m_mutex3.unlock();
if (FileUtils::SearchMethod::DIRECTSEARCH == FileUtils::searchMethod) {
if(FileUtils::SearchMethod::DIRECTSEARCH == FileUtils::searchMethod) {
DirectSearch *directSearch;
directSearch = new DirectSearch(keyword, searchResultFile, searchResultDir, uniqueSymbol1);
m_pool.start(directSearch);
} else if (FileUtils::SearchMethod::INDEXSEARCH == FileUtils::searchMethod) {
} else if(FileUtils::SearchMethod::INDEXSEARCH == FileUtils::searchMethod) {
FileSearch *filesearch;
filesearch = new FileSearch(searchResultFile,uniqueSymbol1,keyword,"0",1,0,5);
filesearch = new FileSearch(searchResultFile, uniqueSymbol1, keyword, "0", 1, 0, 5);
m_pool.start(filesearch);
FileSearch *dirsearch;
dirsearch = new FileSearch(searchResultDir,uniqueSymbol2,keyword,"1",1,0,5);
dirsearch = new FileSearch(searchResultDir, uniqueSymbol2, keyword, "1", 1, 0, 5);
m_pool.start(dirsearch);
FileContentSearch *contentSearch;
contentSearch = new FileContentSearch(searchResultContent,uniqueSymbol3,keyword,0,5);
contentSearch = new FileContentSearch(searchResultContent, uniqueSymbol3, keyword, 0, 5);
m_pool.start(contentSearch);
} else {
qWarning() << "Unknown search method! FileUtils::searchMethod: " << static_cast<int>(FileUtils::searchMethod);
@ -81,11 +77,9 @@ void SearchManager::onKeywordSearch(QString keyword,QQueue<QString> *searchResul
return;
}
bool SearchManager::isBlocked(QString &path)
{
bool SearchManager::isBlocked(QString &path) {
QStringList blockList = GlobalSettings::getInstance()->getBlockDirs();
for(QString i : blockList)
{
for(QString i : blockList) {
if(path.startsWith(i.prepend("/")))
return true;
}
@ -93,8 +87,7 @@ bool SearchManager::isBlocked(QString &path)
}
FileSearch::FileSearch(QQueue<QString> *searchResult,size_t uniqueSymbol, QString keyword, QString value, unsigned slot, int begin, int num)
{
FileSearch::FileSearch(QQueue<QString> *searchResult, size_t uniqueSymbol, QString keyword, QString value, unsigned slot, int begin, int num) {
this->setAutoDelete(true);
m_search_result = searchResult;
m_uniqueSymbol = uniqueSymbol;
@ -105,21 +98,19 @@ FileSearch::FileSearch(QQueue<QString> *searchResult,size_t uniqueSymbol, QStrin
m_num = num;
}
FileSearch::~FileSearch()
{
FileSearch::~FileSearch() {
m_search_result = nullptr;
}
void FileSearch::run()
{
if (!m_search_result->isEmpty()){
void FileSearch::run() {
if(!m_search_result->isEmpty()) {
m_search_result->clear();
}
int resultCount = 0;
int total = 0;
while (total < 100) {
while(total < 100) {
resultCount = keywordSearchfile();
if (resultCount == 0 || resultCount == -1)
if(resultCount == 0 || resultCount == -1)
break;
total += resultCount;
m_begin += m_num;
@ -127,8 +118,7 @@ void FileSearch::run()
return;
}
int FileSearch::keywordSearchfile()
{
int FileSearch::keywordSearchfile() {
try {
qDebug() << "--keywordSearchfile start--";
Xapian::Database db(INDEX_PATH);
@ -136,49 +126,47 @@ int FileSearch::keywordSearchfile()
Xapian::Enquire enquire(db);
Xapian::Query queryFile;
if (!m_value.isEmpty()) {
if(!m_value.isEmpty()) {
std::string slotValue = m_value.toStdString();
Xapian::Query queryValue = Xapian::Query(Xapian::Query::OP_VALUE_RANGE,m_slot,slotValue,slotValue);
queryFile = Xapian::Query(Xapian::Query::OP_AND,query,queryValue);
Xapian::Query queryValue = Xapian::Query(Xapian::Query::OP_VALUE_RANGE, m_slot, slotValue, slotValue);
queryFile = Xapian::Query(Xapian::Query::OP_AND, query, queryValue);
} else {
queryFile = query;
}
qDebug() << "keywordSearchfile:"<<QString::fromStdString(queryFile.get_description());
qDebug() << "keywordSearchfile:" << QString::fromStdString(queryFile.get_description());
enquire.set_query(queryFile);
Xapian::MSet result = enquire.get_mset(m_begin, m_num);
int resultCount = result.size();
qDebug() << "keywordSearchfile results count=" <<resultCount;
if (resultCount == 0)
qDebug() << "keywordSearchfile results count=" << resultCount;
if(resultCount == 0)
return 0;
if (getResult(result) == -1)
if(getResult(result) == -1)
return -1;
qDebug() << "--keywordSearchfile finish--";
return resultCount;
} catch (const Xapian::Error &e) {
qWarning() <<QString::fromStdString(e.get_description());
} catch(const Xapian::Error &e) {
qWarning() << QString::fromStdString(e.get_description());
qDebug() << "--keywordSearchfile finish--";
return -1;
}
}
Xapian::Query FileSearch::creatQueryForFileSearch(Xapian::Database &db)
{
Xapian::Query FileSearch::creatQueryForFileSearch(Xapian::Database &db) {
auto userInput = m_keyword.toLower();
std::vector<Xapian::Query> v;
for (int i=0;i<userInput.size();i++) {
for(int i = 0; i < userInput.size(); i++) {
v.push_back(Xapian::Query(QUrl::toPercentEncoding(userInput.at(i)).toStdString()));
// qDebug()<<QString::fromStdString(Xapian::Query(QString(userInput.at(i)).toStdString()).get_description());
}
Xapian::Query queryPhrase =Xapian::Query(Xapian::Query::OP_PHRASE, v.begin(), v.end());
Xapian::Query queryPhrase = Xapian::Query(Xapian::Query::OP_PHRASE, v.begin(), v.end());
return queryPhrase;
}
int FileSearch::getResult(Xapian::MSet &result)
{
for (auto it = result.begin(); it != result.end(); ++it) {
int FileSearch::getResult(Xapian::MSet &result) {
for(auto it = result.begin(); it != result.end(); ++it) {
Xapian::Document doc = it.get_document();
std::string data = doc.get_data();
Xapian::weight docScoreWeight = it.get_weight();
@ -186,20 +174,20 @@ int FileSearch::getResult(Xapian::MSet &result)
QString path = QString::fromStdString(data);
std::string().swap(data);
if (SearchManager::isBlocked(path)) {
if(SearchManager::isBlocked(path)) {
continue;
}
QFileInfo info(path);
if (!info.exists()) {
if(!info.exists()) {
// pathTobeDelete->append(QString::fromStdString(data));
qDebug()<<path<<"is not exist!!";
qDebug() << path << "is not exist!!";
} else {
switch (m_value.toInt()) {
switch(m_value.toInt()) {
case 1:
SearchManager::m_mutex1.lock();
if (m_uniqueSymbol == SearchManager::uniqueSymbol2) {
if(m_uniqueSymbol == SearchManager::uniqueSymbol2) {
m_search_result->enqueue(path);
SearchManager::m_mutex1.unlock();
} else {
@ -230,8 +218,7 @@ int FileSearch::getResult(Xapian::MSet &result)
return 0;
}
FileContentSearch::FileContentSearch(QQueue<QPair<QString,QStringList>> *searchResult, size_t uniqueSymbol, QString keyword, int begin, int num)
{
FileContentSearch::FileContentSearch(QQueue<QPair<QString, QStringList>> *searchResult, size_t uniqueSymbol, QString keyword, int begin, int num) {
this->setAutoDelete(true);
m_search_result = searchResult;
m_uniqueSymbol = uniqueSymbol;
@ -240,22 +227,20 @@ FileContentSearch::FileContentSearch(QQueue<QPair<QString,QStringList>> *searchR
m_num = num;
}
FileContentSearch::~FileContentSearch()
{
FileContentSearch::~FileContentSearch() {
m_search_result = nullptr;
}
void FileContentSearch::run()
{
if (!m_search_result->isEmpty()) {
void FileContentSearch::run() {
if(!m_search_result->isEmpty()) {
m_search_result->clear();
}
int resultCount = 0;
int total = 0;
while (total<50) {
while(total < 50) {
resultCount = keywordSearchContent();
if (resultCount == 0 || resultCount == -1) {
if(resultCount == 0 || resultCount == -1) {
break;
}
total += resultCount;
@ -264,34 +249,33 @@ void FileContentSearch::run()
return;
}
int FileContentSearch::keywordSearchContent()
{
int FileContentSearch::keywordSearchContent() {
try {
qDebug()<<"--keywordSearchContent search start--";
qDebug() << "--keywordSearchContent search start--";
Xapian::Database db(CONTENT_INDEX_PATH);
Xapian::Enquire enquire(db);
Xapian::QueryParser qp;
qp.set_default_op(Xapian::Query::OP_AND);
qp.set_database(db);
/*
::friso::ResultMap ret;
::friso::FrisoSegmentation::getInstance()->callSegement(ret, keyword.toLocal8Bit().data());
for (::friso::ResultMap::iterator it_map = ret.begin(); it_map != ret.end(); ++it_map){
target_str += it_map->first;
target_str += " ";
it_map->second.first.clear();
::std::vector<size_t>().swap(it_map->second.first);
}
/*
::friso::ResultMap ret;
::friso::FrisoSegmentation::getInstance()->callSegement(ret, keyword.toLocal8Bit().data());
for (::friso::ResultMap::iterator it_map = ret.begin(); it_map != ret.end(); ++it_map){
target_str += it_map->first;
target_str += " ";
it_map->second.first.clear();
::std::vector<size_t>().swap(it_map->second.first);
}
ret.clear();
ret.erase(ret.begin(), ret.end());
::friso::ResultMap().swap(ret);
*/
ret.clear();
ret.erase(ret.begin(), ret.end());
::friso::ResultMap().swap(ret);
*/
QVector<SKeyWord> sKeyWord = ChineseSegmentation::getInstance()->callSegement(m_keyword);
//Creat a query
std::string words;
for (int i=0; i<sKeyWord.size(); i++) {
for(int i = 0; i < sKeyWord.size(); i++) {
words.append(sKeyWord.at(i).word).append(" ");
}
@ -324,16 +308,16 @@ int FileContentSearch::keywordSearchContent()
Xapian::MSet result = enquire.get_mset(m_begin, m_num);
int resultCount = result.size();
if (result.size() == 0) {
if(result.size() == 0) {
return 0;
}
qDebug() << "keywordSearchContent results count=" << resultCount;
if (getResult(result,words) == -1){
if(getResult(result, words) == -1) {
return -1;
}
qDebug()<< "--keywordSearchContent search finish--";
qDebug() << "--keywordSearchContent search finish--";
return resultCount;
} catch(const Xapian::Error &e) {
qWarning() << QString::fromStdString(e.get_description());
@ -342,22 +326,21 @@ int FileContentSearch::keywordSearchContent()
}
}
int FileContentSearch::getResult(Xapian::MSet &result, std::string &keyWord)
{
for (auto it = result.begin(); it != result.end(); ++it) {
int FileContentSearch::getResult(Xapian::MSet &result, std::string &keyWord) {
for(auto it = result.begin(); it != result.end(); ++it) {
Xapian::Document doc = it.get_document();
std::string data = doc.get_data();
double docScoreWeight = it.get_weight();
Xapian::percent docScorePercent = it.get_percent();
QString path = QString::fromStdString(doc.get_value(1));
if (SearchManager::isBlocked(path)){
if(SearchManager::isBlocked(path)) {
continue;
}
QFileInfo info(path);
if (!info.exists()) {
if(!info.exists()) {
// pathTobeDelete->append(QString::fromStdString(data));
qDebug() << path << "is not exist!!";
continue;
@ -367,15 +350,15 @@ int FileContentSearch::getResult(Xapian::MSet &result, std::string &keyWord)
// snippets.append(QString::fromStdString( result.snippet(doc.get_data(),400)));
// qWarning()<<QString::fromStdString(s);
auto term = doc.termlist_begin();
std::string wordTobeFound = QString::fromStdString(keyWord).section(" ",0,0).toStdString();
std::string wordTobeFound = QString::fromStdString(keyWord).section(" ", 0, 0).toStdString();
int size = wordTobeFound.length();
term.skip_to(wordTobeFound);
int count =0;
for (auto pos = term.positionlist_begin();pos != term.positionlist_end()&&count < 6;++pos) {
std::string s = data.substr((*pos < 60)? 0: (*pos - 60) , size + 120);
int count = 0;
for(auto pos = term.positionlist_begin(); pos != term.positionlist_end() && count < 6; ++pos) {
std::string s = data.substr((*pos < 60) ? 0 : (*pos - 60), size + 120);
QString snippet = QString::fromStdString(s);
if (snippet.size() > 6 + QString::fromStdString(keyWord).size()){
snippet.replace(0,3,"...").replace(snippet.size()-3,3,"...");
if(snippet.size() > 6 + QString::fromStdString(keyWord).size()) {
snippet.replace(0, 3, "...").replace(snippet.size() - 3, 3, "...");
} else {
snippet.append("...").prepend("...");
}
@ -402,8 +385,8 @@ int FileContentSearch::getResult(Xapian::MSet &result, std::string &keyWord)
// }
SearchManager::m_mutex3.lock();
if (m_uniqueSymbol == SearchManager::uniqueSymbol3) {
m_search_result->enqueue(qMakePair(path,snippets));
if(m_uniqueSymbol == SearchManager::uniqueSymbol3) {
m_search_result->enqueue(qMakePair(path, snippets));
SearchManager::m_mutex3.unlock();
snippets.clear();
QStringList().swap(snippets);
@ -419,8 +402,7 @@ int FileContentSearch::getResult(Xapian::MSet &result, std::string &keyWord)
return 0;
}
DirectSearch::DirectSearch(QString keyword, QQueue<QString> *searchResultFile, QQueue<QString> *searchResultDir, size_t uniqueSymbol)
{
DirectSearch::DirectSearch(QString keyword, QQueue<QString> *searchResultFile, QQueue<QString> *searchResultDir, size_t uniqueSymbol) {
this->setAutoDelete(true);
m_keyword = keyword;
m_searchResultFile = searchResultFile;
@ -428,8 +410,7 @@ DirectSearch::DirectSearch(QString keyword, QQueue<QString> *searchResultFile, Q
m_uniqueSymbol = uniqueSymbol;
}
void DirectSearch::run()
{
void DirectSearch::run() {
QQueue<QString> bfs;
bfs.enqueue(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
QFileInfoList list;
@ -437,25 +418,25 @@ void DirectSearch::run()
// QDir::Hidden
dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
dir.setSorting(QDir::DirsFirst);
while (!bfs.empty()) {
while(!bfs.empty()) {
dir.setPath(bfs.dequeue());
list = dir.entryInfoList();
for (auto i : list) {
if (i.isDir() && (!(i.isSymLink()))) {
for(auto i : list) {
if(i.isDir() && (!(i.isSymLink()))) {
bfs.enqueue(i.absoluteFilePath());
}
if (i.fileName().contains(m_keyword, Qt::CaseInsensitive)) {
if(i.fileName().contains(m_keyword, Qt::CaseInsensitive)) {
SearchManager::m_mutex1.lock();
// qWarning() << i.fileName() << m_keyword;
if (m_uniqueSymbol == SearchManager::uniqueSymbol1) {
if(m_uniqueSymbol == SearchManager::uniqueSymbol1) {
// TODO
if (i.isDir() && m_searchResultDir->length() < 51) {
if(i.isDir() && m_searchResultDir->length() < 51) {
m_searchResultDir->enqueue(i.absoluteFilePath());
} else if (m_searchResultFile->length() < 51) {
} else if(m_searchResultFile->length() < 51) {
m_searchResultFile->enqueue(i.absoluteFilePath());
}
SearchManager::m_mutex1.unlock();
if (m_searchResultDir->length() > 49 && m_searchResultFile->length() > 49) {
if(m_searchResultDir->length() > 49 && m_searchResultFile->length() > 49) {
return;
}
} else {

View File

@ -46,8 +46,7 @@
#define CONTENT_INDEX_PATH (QStandardPaths::writableLocation(QStandardPaths::HomeLocation)+"/.config/org.ukui/ukui-search/content_index_data").toStdString()
class SearchManager : public QObject
{
class SearchManager : public QObject {
friend class FileSearch;
friend class FileContentSearch;
Q_OBJECT
@ -65,12 +64,12 @@ public:
static QMutex m_mutex3;
public Q_SLOTS:
void onKeywordSearch(QString keyword,QQueue<QString> *searchResultFile,QQueue<QString> *searchResultDir,QQueue<QPair<QString,QStringList>> *searchResultContent);
void onKeywordSearch(QString keyword, QQueue<QString> *searchResultFile, QQueue<QString> *searchResultDir, QQueue<QPair<QString, QStringList>> *searchResultContent);
Q_SIGNALS:
void resultFile(QQueue<QString> *);
void resultDir(QQueue<QString> *);
void resultContent(QQueue<QPair<QString,QStringList>> *);
void resultContent(QQueue<QPair<QString, QStringList>> *);
private:
// int keywordSearchfile(size_t uniqueSymbol, QString keyword, QString value,unsigned slot = 1,int begin = 0, int num = 20);
// int keywordSearchContent(size_t uniqueSymbol, QString keyword, int begin = 0, int num = 20);
@ -96,10 +95,9 @@ private:
QThreadPool m_pool;
};
class FileSearch : public QRunnable
{
class FileSearch : public QRunnable {
public:
explicit FileSearch(QQueue<QString> *searchResult,size_t uniqueSymbol, QString keyword, QString value,unsigned slot = 1,int begin = 0, int num = 20);
explicit FileSearch(QQueue<QString> *searchResult, size_t uniqueSymbol, QString keyword, QString value, unsigned slot = 1, int begin = 0, int num = 20);
~FileSearch();
protected:
void run();
@ -117,26 +115,24 @@ private:
int m_num = 20;
};
class FileContentSearch : public QRunnable
{
class FileContentSearch : public QRunnable {
public:
explicit FileContentSearch(QQueue<QPair<QString,QStringList>> *searchResult,size_t uniqueSymbol, QString keyword, int begin = 0, int num = 20);
explicit FileContentSearch(QQueue<QPair<QString, QStringList>> *searchResult, size_t uniqueSymbol, QString keyword, int begin = 0, int num = 20);
~FileContentSearch();
protected:
void run();
private:
int keywordSearchContent();
int getResult(Xapian::MSet &result,std::string &keyWord);
int getResult(Xapian::MSet &result, std::string &keyWord);
QQueue<QPair<QString,QStringList>> *m_search_result = nullptr;
QQueue<QPair<QString, QStringList>> *m_search_result = nullptr;
size_t m_uniqueSymbol;
QString m_keyword;
int m_begin = 0;
int m_num = 20;
};
class DirectSearch : public QRunnable
{
class DirectSearch : public QRunnable {
public:
explicit DirectSearch(QString keyword, QQueue<QString> *searchResultFile, QQueue<QString> *searchResultDir, size_t uniqueSymbol);
protected:

View File

@ -1,15 +1,14 @@
#include "searchmethodmanager.h"
void SearchMethodManager::searchMethod(FileUtils::SearchMethod sm)
{
void SearchMethodManager::searchMethod(FileUtils::SearchMethod sm) {
qWarning() << "searchMethod start: " << static_cast<int>(sm);
if (FileUtils::SearchMethod::INDEXSEARCH == sm || FileUtils::SearchMethod::DIRECTSEARCH == sm) {
if(FileUtils::SearchMethod::INDEXSEARCH == sm || FileUtils::SearchMethod::DIRECTSEARCH == sm) {
FileUtils::searchMethod = sm;
} else {
printf("enum class error!!!\n");
qWarning("enum class error!!!\n");
}
if (FileUtils::SearchMethod::INDEXSEARCH == sm && 0 == FileUtils::_index_status) {
if(FileUtils::SearchMethod::INDEXSEARCH == sm && 0 == FileUtils::_index_status) {
qWarning() << "start first index";
// m_fi = FirstIndex("/home/zhangzihao/Desktop");
m_fi.start();
@ -17,10 +16,10 @@ void SearchMethodManager::searchMethod(FileUtils::SearchMethod sm)
// InotifyIndex ii("/home");
// ii.start();
this->m_ii = InotifyIndex::getInstance("/home");
if (!this->m_ii->isRunning()) {
if(!this->m_ii->isRunning()) {
this->m_ii->start();
}
qDebug()<<"Search method has been set to INDEXSEARCH";
qDebug() << "Search method has been set to INDEXSEARCH";
}
qWarning() << "searchMethod end: " << static_cast<int>(FileUtils::searchMethod);
}

View File

@ -4,8 +4,7 @@
#include "first-index.h"
#include "inotify-index.h"
class SearchMethodManager
{
class SearchMethodManager {
public:
SearchMethodManager() = default;
void searchMethod(FileUtils::SearchMethod sm);

View File

@ -19,13 +19,12 @@
*/
#include "traverse_bfs.h"
Traverse_BFS::Traverse_BFS(const QString& path)
{
Traverse_BFS::Traverse_BFS(const QString& path) {
Q_ASSERT('/' == path.at(0));
this->path = path;
}
void Traverse_BFS::Traverse(){
void Traverse_BFS::Traverse() {
QQueue<QString> bfs;
bfs.enqueue(this->path);
QFileInfoList list;
@ -33,11 +32,11 @@ void Traverse_BFS::Traverse(){
// QDir::Hidden
dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
dir.setSorting(QDir::DirsFirst);
while (!bfs.empty()) {
while(!bfs.empty()) {
dir.setPath(bfs.dequeue());
list = dir.entryInfoList();
for (auto i : list){
if (i.isDir() && (!(i.isSymLink()))){
for(auto i : list) {
if(i.isDir() && (!(i.isSymLink()))) {
bfs.enqueue(i.absoluteFilePath());
}
DoSomething(i);
@ -45,6 +44,6 @@ void Traverse_BFS::Traverse(){
}
}
void Traverse_BFS::setPath(const QString& path){
void Traverse_BFS::setPath(const QString& path) {
this->path = path;
}

View File

@ -25,8 +25,7 @@
#include <QDir>
#include <QQueue>
class Traverse_BFS
{
class Traverse_BFS {
public:
Traverse_BFS() = default;
void Traverse();

View File

@ -20,25 +20,23 @@
#include "ukui-search-qdbus.h"
#include <QDebug>
UkuiSearchQDBus::UkuiSearchQDBus()
{
UkuiSearchQDBus::UkuiSearchQDBus() {
this->tmpSystemQDBusInterface = new QDBusInterface("com.ukui.search.qt.systemdbus",
"/",
"com.ukui.search.interface",
QDBusConnection::systemBus());
if (!tmpSystemQDBusInterface->isValid()){
"/",
"com.ukui.search.interface",
QDBusConnection::systemBus());
if(!tmpSystemQDBusInterface->isValid()) {
qCritical() << "Create Client Interface Failed When execute chage: " << QDBusConnection::systemBus().lastError();
return;
}
}
UkuiSearchQDBus::~UkuiSearchQDBus(){
UkuiSearchQDBus::~UkuiSearchQDBus() {
delete this->tmpSystemQDBusInterface;
this->tmpSystemQDBusInterface = nullptr;
}
//一键三连
void UkuiSearchQDBus::setInotifyMaxUserWatches()
{
void UkuiSearchQDBus::setInotifyMaxUserWatches() {
// /proc/sys/fs/inotify/max_user_watches
this->tmpSystemQDBusInterface->call("setInotifyMaxUserWatchesStep1");
// sysctl

View File

@ -22,8 +22,7 @@
#include <QDBusInterface>
class UkuiSearchQDBus
{
class UkuiSearchQDBus {
public:
UkuiSearchQDBus();
~UkuiSearchQDBus();

View File

@ -32,8 +32,7 @@
#include "index/inotify-index.h"
#include "index/search-manager.h"
class LIBSEARCH_EXPORT GlobalSearch
{
class LIBSEARCH_EXPORT GlobalSearch {
public:
static QStringList fileSearch(QString keyword, int begin = 0, int num = -1);

File diff suppressed because it is too large Load Diff

View File

@ -7,22 +7,19 @@
#define UCHAR unsigned char
#define USHORT unsigned short
typedef enum
{
Word = 0,
Excel,
Ppt
}TYPE;
typedef enum {
Word = 0,
Excel,
Ppt
} TYPE;
/* Property Set Storage */
typedef struct pps_tag
{
typedef struct pps_tag {
ULONG ulSB;
ULONG ulSize;
} ppsTag;
typedef struct pps_info_tag
{
typedef struct pps_info_tag {
ppsTag tWordDocument; /* Text stream */
ppsTag tWorkBook;
ppsTag tPPTDocument;
@ -37,8 +34,7 @@ typedef struct pps_info_tag
} ppsInfoType;
/* Private type for Property Set Storage entries */
typedef struct pps_entry_tag
{
typedef struct pps_entry_tag {
ULONG ulNext;
ULONG ulPrevious;
ULONG ulDir;
@ -50,10 +46,8 @@ typedef struct pps_entry_tag
} ppsEntryType;
/* Excel Record Struct*/
typedef struct excelRecord
{
excelRecord()
{
typedef struct excelRecord {
excelRecord() {
usLen = 0;
usRichLen = 0;
ulWLen = 0;
@ -65,52 +59,49 @@ typedef struct excelRecord
bool bUni;
} excelRecord;
typedef struct readDataParam
{
readDataParam()
{
ulStBlk = 0;
pFile = NULL;
ulBBd = NULL;
tBBdLen = 0;
usBlkSize = 0;
}
ulong ulStBlk;
FILE *pFile;
ulong *ulBBd;
size_t tBBdLen;
ushort usBlkSize;
}rdPara;
typedef struct readDataParam {
readDataParam() {
ulStBlk = 0;
pFile = NULL;
ulBBd = NULL;
tBBdLen = 0;
usBlkSize = 0;
}
ulong ulStBlk;
FILE *pFile;
ulong *ulBBd;
size_t tBBdLen;
ushort usBlkSize;
} rdPara;
class KBinaryParser :public QObject
{
Q_OBJECT
class KBinaryParser : public QObject {
Q_OBJECT
public:
KBinaryParser(QObject *parent=0);
~KBinaryParser();
KBinaryParser(QObject *parent = 0);
~KBinaryParser();
public:
bool RunParser(QString strFile,QString &content);
bool RunParser(QString strFile, QString &content);
private:
bool bGetPPS(FILE *pFile,
const ULONG *aulRootList, size_t tRootListLen, ppsInfoType *pPPS);
bool bGetPPS(FILE *pFile,
const ULONG *aulRootList, size_t tRootListLen, ppsInfoType *pPPS);
int readData(rdPara &readParam, uchar *aucBuffer, ulong ulOffset, size_t tToRead);
int readData(rdPara &readParam, uchar *aucBuffer, ulong ulOffset, size_t tToRead);
int InitDocOle(FILE *pFile,long lFilesize,QString &content);
int InitDocOle(FILE *pFile, long lFilesize, QString &content);
bool read8DocText(FILE *pFile, const ppsInfoType *pPPS,
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader,QString &content);
const ULONG *aulBBD, size_t tBBDLen,
const ULONG *aulSBD, size_t tSBDLen,
const UCHAR *aucHeader, QString &content);
int readSSTRecord(readDataParam &rdParam, ppsInfoType, ulong &ulOff, ushort usPartLen,QString &content);
int readSSTRecord(readDataParam &rdParam, ppsInfoType, ulong &ulOff, ushort usPartLen, QString &content);
int read8BiffRecord(uchar uFlag, ulong ulOff, ulong &ulNext, readDataParam &rdParam, excelRecord &eR);
ULONG readPPtRecord(FILE* pFile, ppsInfoType* PPS_info, ULONG* aulBBD,
size_t tBBDLen, ULONG ulPos,QString &content);
size_t tBBDLen, ULONG ulPos, QString &content);
QString m_strFileName;
QString m_strFileName;
};
#endif // SEARCHHELPER_H

View File

@ -19,8 +19,7 @@
*/
#include "setting-match.h"
#include "file-utils.h"
SettingsMatch::SettingsMatch(QObject *parent) : QObject(parent)
{
SettingsMatch::SettingsMatch(QObject *parent) : QObject(parent) {
xmlElement();
}
@ -31,9 +30,9 @@ SettingsMatch::SettingsMatch(QObject *parent) : QObject(parent)
*
* @return
*/
QStringList SettingsMatch::startMatchApp(const QString &source){
m_sourceText=source;
QStringList settingList=matching();
QStringList SettingsMatch::startMatchApp(const QString &source) {
m_sourceText = source;
QStringList settingList = matching();
return settingList;
}
@ -41,42 +40,42 @@ QStringList SettingsMatch::startMatchApp(const QString &source){
* @brief SettingsMatch::xmlElement
* xml文件内容读到内存
*/
void SettingsMatch::xmlElement(){
void SettingsMatch::xmlElement() {
QString ChineseIndex;
QString EnglishIndex;
QFile file(QString::fromLocal8Bit("/usr/share/ukui-control-center/shell/res/search.xml"));
if (!file.open(QIODevice::ReadOnly)){
if(!file.open(QIODevice::ReadOnly)) {
return;
}
QDomDocument doc;
doc.setContent(&file);
QDomElement root=doc.documentElement();
QDomElement root = doc.documentElement();
QDomNode node = root.previousSibling();
node=root.firstChild();
node = root.firstChild();
while(!node.isNull()){
QDomElement element=node.toElement();
QString key=element.attribute("name");;
m_chine_searchResult=m_chine_searchList.value(key);
m_English_searchResult=m_English_searchList.value(key);
QDomNodeList list=element.childNodes();
for(int i=0;i<list.count();++i){
QDomNode n=list.at(i);
if(n.nodeName()==QString::fromLocal8Bit("ChinesePlugin")){
ChineseIndex=n.toElement().text();
}
if(n.nodeName()==QString::fromLocal8Bit("ChineseFunc")){
ChineseIndex+=QString::fromLocal8Bit("/")+n.toElement().text();
m_chine_searchResult.append(ChineseIndex);
}
if(n.nodeName()==QString::fromLocal8Bit("EnglishFunc")){
EnglishIndex=QString::fromLocal8Bit("/")+n.toElement().text();
m_English_searchResult.append(EnglishIndex);
}
}
m_chine_searchList.insert(key,m_chine_searchResult);
m_English_searchList.insert(key,m_English_searchResult);
node=node.nextSibling();
while(!node.isNull()) {
QDomElement element = node.toElement();
QString key = element.attribute("name");;
m_chine_searchResult = m_chine_searchList.value(key);
m_English_searchResult = m_English_searchList.value(key);
QDomNodeList list = element.childNodes();
for(int i = 0; i < list.count(); ++i) {
QDomNode n = list.at(i);
if(n.nodeName() == QString::fromLocal8Bit("ChinesePlugin")) {
ChineseIndex = n.toElement().text();
}
if(n.nodeName() == QString::fromLocal8Bit("ChineseFunc")) {
ChineseIndex += QString::fromLocal8Bit("/") + n.toElement().text();
m_chine_searchResult.append(ChineseIndex);
}
if(n.nodeName() == QString::fromLocal8Bit("EnglishFunc")) {
EnglishIndex = QString::fromLocal8Bit("/") + n.toElement().text();
m_English_searchResult.append(EnglishIndex);
}
}
m_chine_searchList.insert(key, m_chine_searchResult);
m_English_searchList.insert(key, m_English_searchResult);
node = node.nextSibling();
}
file.close();
}
@ -86,42 +85,40 @@ void SettingsMatch::xmlElement(){
*
* @return
*/
QStringList SettingsMatch::matching(){
QStringList SettingsMatch::matching() {
QStringList returnresult;
QStringList regmatch;
QString key;
QStringList pinyinlist;
QMap<QString, QStringList>::const_iterator i;
QLocale ql;
if(ql.language()==QLocale::Chinese){
for(i=m_chine_searchList.constBegin();i!=m_chine_searchList.constEnd();++i){
regmatch=*i;
key=i.key();
for(int t=0; t<regmatch.size();t++)
{
if(m_sourceText=="/")
if(ql.language() == QLocale::Chinese) {
for(i = m_chine_searchList.constBegin(); i != m_chine_searchList.constEnd(); ++i) {
regmatch = *i;
key = i.key();
for(int t = 0; t < regmatch.size(); t++) {
if(m_sourceText == "/")
continue;
QString str =regmatch.at(t);
pinyinlist=FileUtils::findMultiToneWords(str);
if(str.contains(m_sourceText))
{
str=key+"/"+str;
QString str = regmatch.at(t);
pinyinlist = FileUtils::findMultiToneWords(str);
if(str.contains(m_sourceText)) {
str = key + "/" + str;
returnresult.append(str);//中文名
continue;
}
for(int i = 0;i<pinyinlist.size()/2;i++){
str =regmatch.at(t);
QString shouzimu=pinyinlist.at(2*i+1); // 中文转首字母
if(shouzimu.contains(m_sourceText,Qt::CaseInsensitive)){
str=key+"/"+str;
for(int i = 0; i < pinyinlist.size() / 2; i++) {
str = regmatch.at(t);
QString shouzimu = pinyinlist.at(2 * i + 1); // 中文转首字母
if(shouzimu.contains(m_sourceText, Qt::CaseInsensitive)) {
str = key + "/" + str;
returnresult.append(str);
break;
}
if(m_sourceText.size()<2)
if(m_sourceText.size() < 2)
break;
QString pinyin=pinyinlist.at(2*i);// 中文转拼音
if(pinyin.contains(m_sourceText,Qt::CaseInsensitive)){
str=key+"/"+str;
QString pinyin = pinyinlist.at(2 * i); // 中文转拼音
if(pinyin.contains(m_sourceText, Qt::CaseInsensitive)) {
str = key + "/" + str;
returnresult.append(str);
break;
}
@ -130,17 +127,16 @@ QStringList SettingsMatch::matching(){
}
}
}
if(ql.language()==QLocale::English){
for(i=m_English_searchList.constBegin();i!=m_English_searchList.constEnd();++i){
regmatch=*i;
key=i.key();
for(int t=0; t<regmatch.size();t++)
{
if(m_sourceText=="/")
if(ql.language() == QLocale::English) {
for(i = m_English_searchList.constBegin(); i != m_English_searchList.constEnd(); ++i) {
regmatch = *i;
key = i.key();
for(int t = 0; t < regmatch.size(); t++) {
if(m_sourceText == "/")
continue;
QString str =regmatch.at(t);
if(str.contains(m_sourceText,Qt::CaseInsensitive)){
str=key+"/"+str;
QString str = regmatch.at(t);
if(str.contains(m_sourceText, Qt::CaseInsensitive)) {
str = key + "/" + str;
returnresult.append(str);
}
}

View File

@ -30,8 +30,7 @@
#include <QStringList>
#include <QTimer>
#include <QDebug>
class SettingsMatch : public QObject
{
class SettingsMatch : public QObject {
Q_OBJECT
public:
explicit SettingsMatch(QObject *parent = nullptr);
@ -42,8 +41,8 @@ private:
QStringList matching();
private:
QMap<QString,QStringList> m_chine_searchList;
QMap<QString,QStringList> m_English_searchList;
QMap<QString, QStringList> m_chine_searchList;
QMap<QString, QStringList> m_English_searchList;
QStringList m_chine_searchResult;
QStringList m_English_searchResult;
QString m_sourceText;

View File

@ -24,26 +24,24 @@
#include <QTimer>
#include "config-file.h"
ContentWidget::ContentWidget(QWidget * parent):QStackedWidget(parent)
{
ContentWidget::ContentWidget(QWidget * parent): QStackedWidget(parent) {
initUI();
initListView();
//快速入口应用列表
// m_quicklyOpenList<<"/usr/share/applications/peony.desktop"<<"/usr/share/applications/ukui-control-center.desktop"<<"/usr/share/applications/ksc-defender.desktop";
m_quicklyOpenList << "/usr/share/applications/ksc-defender.desktop"
<< "/usr/share/applications/ukui-notebook.desktop"
<< "/usr/share/applications/eom.desktop"
<< "/usr/share/applications/pluma.desktop"
<< "/usr/share/applications/claws-mail.desktop" ;
<< "/usr/share/applications/ukui-notebook.desktop"
<< "/usr/share/applications/eom.desktop"
<< "/usr/share/applications/pluma.desktop"
<< "/usr/share/applications/claws-mail.desktop" ;
}
ContentWidget::~ContentWidget()
{
if (m_homePage) {
ContentWidget::~ContentWidget() {
if(m_homePage) {
delete m_homePage;
m_homePage = nullptr;
}
if (m_resultPage) {
if(m_resultPage) {
delete m_resultPage;
m_resultPage = nullptr;
}
@ -56,7 +54,7 @@ void ContentWidget::initUI() {
m_homePage = new QWidget(this);
m_homePageLyt = new QVBoxLayout(m_homePage);
m_homePageLyt->setSpacing(0);
m_homePageLyt->setContentsMargins(0,0,0,0);
m_homePageLyt->setContentsMargins(0, 0, 0, 0);
m_homePage->setLayout(m_homePageLyt);
m_resultPage = new QWidget(this);
@ -103,8 +101,7 @@ void ContentWidget::initUI() {
/**
* @brief ContentWidget::initListView
*/
void ContentWidget::initListView()
{
void ContentWidget::initListView() {
m_fileListView = new SearchListView(m_resultList, QStringList(), SearchItem::SearchType::Files);
m_dirListView = new SearchListView(m_resultList, QStringList(), SearchItem::SearchType::Dirs);
m_contentListView = new SearchListView(m_resultList, QStringList(), SearchItem::SearchType::Contents);
@ -232,8 +229,7 @@ void ContentWidget::initListView()
/**
* @brief ContentWidget::hideListView
*/
void ContentWidget::hideListView()
{
void ContentWidget::hideListView() {
m_bestTitleLabel->hide();
m_bestListView->hide();
m_appTitleLabel->hide();
@ -262,16 +258,16 @@ void ContentWidget::hideListView()
void ContentWidget::setupConnect(SearchListView * listview) {
connect(this, &ContentWidget::currentItemChanged, listview, [ = ]() {
if (! listview->is_current_list) {
if(! listview->is_current_list) {
listview->blockSignals(true);
listview->clearSelection();
listview->blockSignals(false);
}
});
connect(listview,&SearchListView::currentSelectPos,[=](QPoint pos){
m_resultListArea->ensureVisible(pos.x(),pos.y());
connect(listview, &SearchListView::currentSelectPos, [ = ](QPoint pos) {
m_resultListArea->ensureVisible(pos.x(), pos.y());
});
connect(listview,&SearchListView::mousePressed,this,&ContentWidget::mousePressed);
connect(listview, &SearchListView::mousePressed, this, &ContentWidget::mousePressed);
connect(listview, &SearchListView::currentRowChanged, this, &ContentWidget::onListViewRowChanged);
connect(listview, &SearchListView::onRowDoubleClicked, this, &ContentWidget::onListViewRowDoubleClicked);
}
@ -279,57 +275,55 @@ void ContentWidget::setupConnect(SearchListView * listview) {
/**
* @brief ContentWidget::resetHeight
*/
void ContentWidget::resetListHeight()
{
void ContentWidget::resetListHeight() {
int height = 0;
if (! m_bestListView->isHidden) {
if(! m_bestListView->isHidden) {
height += m_bestTitleLabel->height();
height += m_bestListView->height();
}
if (! m_appListView->isHidden) {
if(! m_appListView->isHidden) {
height += m_appTitleLabel->height();
height += m_appListView->height();
if (m_appShowMoreLabel->isVisible()) {
if(m_appShowMoreLabel->isVisible()) {
height += m_appShowMoreLabel->height();
}
}
if (! m_settingListView->isHidden) {
if(! m_settingListView->isHidden) {
height += m_settingTitleLabel->height();
height += m_settingListView->height();
if (m_settingShowMoreLabel->isVisible()) {
if(m_settingShowMoreLabel->isVisible()) {
height += m_settingShowMoreLabel->height();
}
}
if (! m_fileListView->isHidden) {
if(! m_fileListView->isHidden) {
height += m_fileTitleLabel->height();
height += m_fileListView->height();
if (m_fileShowMoreLabel->isVisible()) {
if(m_fileShowMoreLabel->isVisible()) {
height += m_fileShowMoreLabel->height();
}
}
if (! m_dirListView->isHidden) {
if(! m_dirListView->isHidden) {
height += m_dirTitleLabel->height();
height += m_dirListView->height();
if (m_dirShowMoreLabel->isVisible()) {
if(m_dirShowMoreLabel->isVisible()) {
height += m_dirShowMoreLabel->height();
}
}
if (! m_contentListView->isHidden) {
if(! m_contentListView->isHidden) {
height += m_contentTitleLabel->height();
height += m_contentListView->height();
if (m_contentShowMoreLabel->isVisible()) {
if(m_contentShowMoreLabel->isVisible()) {
height += m_contentShowMoreLabel->height();
}
}
if (! m_webListView->isHidden) {
if(! m_webListView->isHidden) {
height += m_webTitleLabel->height();
height += m_webListView->height();
}
m_resultList->setFixedHeight(height);
}
void ContentWidget::appendBestItem(const int &type, const QString &path)
{
void ContentWidget::appendBestItem(const int &type, const QString &path) {
m_bestList.append(QPair<int, QString>(type, path));
m_bestListView->appendBestItem(QPair<int, QString>(type, path));
appendSearchItem(SearchItem::SearchType::Best, path);
@ -351,27 +345,27 @@ void ContentWidget::initHomePage() {
lists.append(recentlyList);
lists.append(commonlyList);
for (int i = 0; i < lists.count(); i++) {
if (lists.at(i).isEmpty())
for(int i = 0; i < lists.count(); i++) {
if(lists.at(i).isEmpty())
continue;
QWidget * listWidget = new QWidget(m_homePage);
QVBoxLayout * itemWidgetLyt = new QVBoxLayout(listWidget);
QLabel * titleLabel = new QLabel(listWidget);
QWidget * itemWidget = new QWidget(listWidget);
if (i == 1) {
if (lists.at(i).length() <= 2) itemWidget->setFixedHeight(48);
if(i == 1) {
if(lists.at(i).length() <= 2) itemWidget->setFixedHeight(48);
else itemWidget->setFixedHeight(104);
titleLabel->setText(tr("Recently Opened"));
QGridLayout * layout = new QGridLayout(itemWidget);
layout->setSpacing(8);
layout->setContentsMargins(0, 0, 0, 0);
itemWidget->setLayout(layout);
for (int j = 0; j < lists.at(i).count(); j++) {
for(int j = 0; j < lists.at(i).count(); j++) {
HomePageItem * item = new HomePageItem(itemWidget, i, lists.at(i).at(j));
item->setFixedSize(300, 48);
layout->addWidget(item, j / 2, j % 2);
}
if (lists.at(i).length() == 1) {
if(lists.at(i).length() == 1) {
QWidget * emptyItem = new QWidget(itemWidget);
emptyItem->setFixedSize(300, 48); //占位用widget,只有一项时在右方补全
layout->addWidget(emptyItem, 1, 2);
@ -383,8 +377,8 @@ void ContentWidget::initHomePage() {
layout->setContentsMargins(0, 0, 0, 0);
itemWidget->setLayout(layout);
int shownItem = lists.at(i).length();
Q_FOREACH(QString path, lists.at(i)){
if (i == 0 && QString::compare(FileUtils::getAppName(path),"Unknown App") == 0) {
Q_FOREACH(QString path, lists.at(i)) {
if(i == 0 && QString::compare(FileUtils::getAppName(path), "Unknown App") == 0) {
shownItem --;
continue;
}
@ -392,12 +386,12 @@ void ContentWidget::initHomePage() {
item->setFixedSize(116, 116);
layout->addWidget(item);
}
for (int j = 0; j < 5 - shownItem; j++) {
for(int j = 0; j < 5 - shownItem; j++) {
QWidget * emptyItem = new QWidget(itemWidget);
emptyItem->setFixedSize(116, 116); //占位用widget,少于5项会补全后方占位
layout->addWidget(emptyItem);
}
if (i == 0 && shownItem) titleLabel->setText(tr("Open Quickly"));
if(i == 0 && shownItem) titleLabel->setText(tr("Open Quickly"));
else titleLabel->setText(tr("Commonly Used"));
}
itemWidgetLyt->setSpacing(6);
@ -428,51 +422,50 @@ int ContentWidget::currentPage() {
/**
* @brief ContentWidget::resetSearchList
*/
void ContentWidget::resetSearchList()
{
void ContentWidget::resetSearchList() {
// this->hideListView();
if (m_fileListView) {
if(m_fileListView) {
m_fileListView->hide();
m_fileTitleLabel->hide();
m_fileShowMoreLabel->hide();
m_fileListView->isHidden = true;
m_fileListView->clear();
}
if (m_dirListView) {
if(m_dirListView) {
m_dirListView->hide();
m_dirTitleLabel->hide();
m_dirShowMoreLabel->hide();
m_dirListView->isHidden = true;
m_dirListView->clear();
}
if (m_contentListView) {
if(m_contentListView) {
m_contentListView->hide();
m_contentTitleLabel->hide();
m_contentShowMoreLabel->hide();
m_contentListView->isHidden = true;
m_contentListView->clear();
}
if (m_appListView) {
if(m_appListView) {
m_appListView->hide();
m_appTitleLabel->hide();
m_appShowMoreLabel->hide();
m_appListView->isHidden = true;
m_appListView->clear();
}
if (m_settingListView) {
if(m_settingListView) {
m_settingListView->hide();
m_settingTitleLabel->hide();
m_settingShowMoreLabel->hide();
m_settingListView->isHidden = true;
m_settingListView->clear();
}
if (m_bestListView) {
if(m_bestListView) {
m_bestListView->hide();
m_bestTitleLabel->hide();
m_bestListView->isHidden = true;
m_bestListView->clear();
}
if (m_webListView) {
if(m_webListView) {
m_webListView->clear();
m_webListView->appendItem(m_keyword);
m_webTitleLabel->show();
@ -492,21 +485,21 @@ void ContentWidget::resetSearchList()
m_contentShowMoreLabel->resetLabel();
m_bestList.clear();
if (! m_appList.isEmpty())
if(! m_appList.isEmpty())
m_appList.clear();
if (! m_settingList.isEmpty())
if(! m_settingList.isEmpty())
m_settingList.clear();
if (! m_dirList.isEmpty())
if(! m_dirList.isEmpty())
m_dirList.clear();
if (! m_fileList.isEmpty())
if(! m_fileList.isEmpty())
m_fileList.clear();
if (! m_contentList.isEmpty())
if(! m_contentList.isEmpty())
m_contentList.clear();
if (! m_appPathList.isEmpty())
if(! m_appPathList.isEmpty())
m_appPathList.clear();
if (! m_appIconList.isEmpty())
if(! m_appIconList.isEmpty())
m_appIconList.clear();
if (!m_appDescList.isEmpty())
if(!m_appDescList.isEmpty())
m_appDescList.clear();
}
@ -514,17 +507,16 @@ void ContentWidget::resetSearchList()
* @brief ContentWidget::setSettingList
* @param settingList
*/
void ContentWidget::setSettingList(const QStringList & settingList)
{
if (settingList.isEmpty())
void ContentWidget::setSettingList(const QStringList & settingList) {
if(settingList.isEmpty())
return;
m_settingList = settingList;
qDebug()<<"Append a best item into list: "<<settingList.at(0);
qDebug() << "Append a best item into list: " << settingList.at(0);
this->appendBestItem(SearchItem::SearchType::Settings, settingList.at(0));
m_settingListView->show();
m_settingTitleLabel->show();
m_settingListView->isHidden = false;
if (m_settingList.length() <= 5) {
if(m_settingList.length() <= 5) {
m_settingListView->setList(m_settingList);
} else {
m_settingShowMoreLabel->show();
@ -538,16 +530,16 @@ void ContentWidget::setSettingList(const QStringList & settingList)
* @param appList QVector<namelist,pathlist,iconlist>
*/
void ContentWidget::setAppList(const QVector<QStringList>& appList) {
if (appList.at(0).isEmpty())
if(appList.at(0).isEmpty())
return;
m_appList = appList.at(0);
m_appPathList = appList.at(1);
m_appIconList = appList.at(2);
m_appDescList = appList.at(3);
m_appListView->setAppList(m_appPathList, m_appIconList);
qDebug()<<"Append a best item into list: "<<appList.at(0).at(0);
qDebug() << "Append a best item into list: " << appList.at(0).at(0);
SearchItemModel * model = qobject_cast<SearchItemModel *>(m_bestListView->model());
if (appList.at(1).at(0).isEmpty() || appList.at(1).at(0) == "") {
if(appList.at(1).at(0).isEmpty() || appList.at(1).at(0) == "") {
model->setBestAppIcon(appList.at(2).at(0), false);
} else {
model->setBestAppIcon(appList.at(2).at(0), true);
@ -556,7 +548,7 @@ void ContentWidget::setAppList(const QVector<QStringList>& appList) {
m_appListView->show();
m_appTitleLabel->show();
m_appListView->isHidden = false;
if (m_appList.length() <= 5) {
if(m_appList.length() <= 5) {
m_appListView->setList(m_appList);
} else {
m_appShowMoreLabel->show();
@ -572,86 +564,86 @@ void ContentWidget::setAppList(const QVector<QStringList>& appList) {
* @param contents
*/
void ContentWidget::appendSearchItem(const int& type, const QString& path, QStringList contents) {
switch (type) {
case SearchItem::SearchType::Best: {
if (m_bestListView->isHidden) {
m_bestListView->show();
m_bestTitleLabel->show();
m_bestListView->isHidden = false;
}
m_bestListView->appendItem(path);
if (m_detailView->isEmpty()) {
m_bestListView->setCurrentIndex(m_bestListView->model()->index(0, 0, QModelIndex()));
}
break;
switch(type) {
case SearchItem::SearchType::Best: {
if(m_bestListView->isHidden) {
m_bestListView->show();
m_bestTitleLabel->show();
m_bestListView->isHidden = false;
}
case SearchItem::SearchType::Files: {
if (m_fileListView->isHidden) {
m_fileListView->show();
m_fileTitleLabel->show();
m_fileListView->isHidden = false;
this->appendBestItem(SearchItem::SearchType::Files, path);
}
if (m_fileListView->getLength() < 5) { //当已搜索结果列表少于5项直接将搜索结果添加到列表中
m_fileListView->appendItem(path);
} else if (m_fileListView->getLength() == 5) { //当已搜索结果等于5项新增的被折叠显示“展开”按钮
m_fileShowMoreLabel->show();
} else { //当搜索列表显示的大于5项说明列表被展开可以继续把新增项添加到列表中
m_fileListView->appendItem(path);
}
m_fileList.append(path);
break;;
m_bestListView->appendItem(path);
if(m_detailView->isEmpty()) {
m_bestListView->setCurrentIndex(m_bestListView->model()->index(0, 0, QModelIndex()));
}
case SearchItem::SearchType::Dirs: {
if (m_dirListView->isHidden) {
m_dirListView->show();
m_dirTitleLabel->show();
m_dirListView->isHidden = false;
this->appendBestItem(SearchItem::SearchType::Dirs, path);
}
if (m_dirListView->getLength() < 5) {
m_dirListView->appendItem(path);
} else if (m_dirListView->getLength() == 5) {
m_dirShowMoreLabel->show();
} else {
m_dirListView->appendItem(path);
}
m_dirList.append(path);
break;
break;
}
case SearchItem::SearchType::Files: {
if(m_fileListView->isHidden) {
m_fileListView->show();
m_fileTitleLabel->show();
m_fileListView->isHidden = false;
this->appendBestItem(SearchItem::SearchType::Files, path);
}
case SearchItem::SearchType::Contents: {
if (m_contentListView->isHidden) {
m_contentListView->show();
m_contentTitleLabel->show();
m_contentListView->isHidden = false;
for (int i = 0; i < contents.length(); i ++) {
m_bestContent.append(contents.at(i));
if (i != contents.length() - 1) {
m_bestContent.append("\n");
}
}
this->appendBestItem(SearchItem::SearchType::Contents, path);
}
if (m_contentListView->getLength() < 5) {
m_contentListView->appendItem(path);
} else if (m_contentListView->getLength() == 5) {
m_contentShowMoreLabel->show();
} else {
m_contentListView->appendItem(path);
}
m_contentList.append(path);
QString temp;
for (int i = 0; i < contents.length(); i ++) {
temp.append(contents.at(i));
if (i != contents.length() - 1) {
temp.append("\n");
if(m_fileListView->getLength() < 5) { //当已搜索结果列表少于5项直接将搜索结果添加到列表中
m_fileListView->appendItem(path);
} else if(m_fileListView->getLength() == 5) { //当已搜索结果等于5项新增的被折叠显示“展开”按钮
m_fileShowMoreLabel->show();
} else { //当搜索列表显示的大于5项说明列表被展开可以继续把新增项添加到列表中
m_fileListView->appendItem(path);
}
m_fileList.append(path);
break;;
}
case SearchItem::SearchType::Dirs: {
if(m_dirListView->isHidden) {
m_dirListView->show();
m_dirTitleLabel->show();
m_dirListView->isHidden = false;
this->appendBestItem(SearchItem::SearchType::Dirs, path);
}
if(m_dirListView->getLength() < 5) {
m_dirListView->appendItem(path);
} else if(m_dirListView->getLength() == 5) {
m_dirShowMoreLabel->show();
} else {
m_dirListView->appendItem(path);
}
m_dirList.append(path);
break;
}
case SearchItem::SearchType::Contents: {
if(m_contentListView->isHidden) {
m_contentListView->show();
m_contentTitleLabel->show();
m_contentListView->isHidden = false;
for(int i = 0; i < contents.length(); i ++) {
m_bestContent.append(contents.at(i));
if(i != contents.length() - 1) {
m_bestContent.append("\n");
}
}
m_contentDetailList.append(temp);
break;
this->appendBestItem(SearchItem::SearchType::Contents, path);
}
default:
break;
if(m_contentListView->getLength() < 5) {
m_contentListView->appendItem(path);
} else if(m_contentListView->getLength() == 5) {
m_contentShowMoreLabel->show();
} else {
m_contentListView->appendItem(path);
}
m_contentList.append(path);
QString temp;
for(int i = 0; i < contents.length(); i ++) {
temp.append(contents.at(i));
if(i != contents.length() - 1) {
temp.append("\n");
}
}
m_contentDetailList.append(temp);
break;
}
default:
break;
}
this->resetListHeight();
return;
@ -663,23 +655,23 @@ void ContentWidget::appendSearchItem(const int& type, const QString& path, QStri
* @return
*/
QString ContentWidget::getTitleName(const int& type) {
switch (type) {
case SearchItem::SearchType::Apps :
return tr("Apps");
case SearchItem::SearchType::Settings :
return tr("Settings");
case SearchItem::SearchType::Files :
return tr("Files");
case SearchItem::SearchType::Dirs :
return tr("Dirs");
case SearchItem::SearchType::Contents :
return tr("File Contents");
case SearchItem::SearchType::Best :
return tr("Best Matches");
case SearchItem::SearchType::Web :
return tr("Web Pages");
default :
return tr("Unknown");
switch(type) {
case SearchItem::SearchType::Apps :
return tr("Apps");
case SearchItem::SearchType::Settings :
return tr("Settings");
case SearchItem::SearchType::Files :
return tr("Files");
case SearchItem::SearchType::Dirs :
return tr("Dirs");
case SearchItem::SearchType::Contents :
return tr("File Contents");
case SearchItem::SearchType::Best :
return tr("Best Matches");
case SearchItem::SearchType::Web :
return tr("Web Pages");
default :
return tr("Unknown");
}
}
@ -688,11 +680,10 @@ QString ContentWidget::getTitleName(const int& type) {
* @param layout
*/
void ContentWidget::clearLayout(QLayout * layout) {
if (! layout) return;
if(! layout) return;
QLayoutItem * child;
while ((child = layout->takeAt(0)) != 0) {
if(child->widget())
{
while((child = layout->takeAt(0)) != 0) {
if(child->widget()) {
child->widget()->setParent(NULL); //防止删除后窗口看上去没有消失
}
delete child;
@ -705,12 +696,11 @@ void ContentWidget::clearLayout(QLayout * layout) {
* @param type
* @param path
*/
void ContentWidget::onListViewRowChanged(SearchListView * listview, const int &type, const QString &path)
{
void ContentWidget::onListViewRowChanged(SearchListView * listview, const int &type, const QString &path) {
if(type == SearchItem::SearchType::Contents && !m_contentDetailList.isEmpty()) {
m_detailView->isContent = true;
m_detailView->setContent(m_contentDetailList.at(listview->currentIndex().row()), m_keyword);
} else if (type == SearchItem::SearchType::Best && !m_bestContent.isEmpty() && listview->currentIndex().row() == listview->getLength() - 1) {
} else if(type == SearchItem::SearchType::Best && !m_bestContent.isEmpty() && listview->currentIndex().row() == listview->getLength() - 1) {
m_detailView->setContent(m_bestContent, m_keyword);
m_detailView->isContent = true;
m_detailView->setupWidget(SearchItem::SearchType::Contents, path);
@ -721,14 +711,14 @@ void ContentWidget::onListViewRowChanged(SearchListView * listview, const int &t
} else {
m_detailView->isContent = false;
}
if (type == SearchItem::SearchType::Web) {
if(type == SearchItem::SearchType::Web) {
m_detailView->setWebWidget(this->m_keyword);
} else if (type == SearchItem::SearchType::Apps) {
} else if(type == SearchItem::SearchType::Apps) {
int index = listview->currentIndex().row();
m_detailView->setAppWidget(m_appList.at(index), m_appPathList.at(index), m_appIconList.at(index), m_appDescList.at(index));
} else if (type == SearchItem::SearchType::Best) {
if (m_bestList.at(listview->currentIndex().row()).first == SearchItem::SearchType::Apps) {
m_detailView->setAppWidget(m_appList.at(0), m_appPathList.at(0), m_appIconList.at(0), m_appDescList.at(0));
} else if(type == SearchItem::SearchType::Best) {
if(m_bestList.at(listview->currentIndex().row()).first == SearchItem::SearchType::Apps) {
m_detailView->setAppWidget(m_appList.at(0), m_appPathList.at(0), m_appIconList.at(0), m_appDescList.at(0));
} else {
m_detailView->setupWidget(m_bestList.at(listview->currentIndex().row()).first, m_bestList.at(listview->currentIndex().row()).second);
}
@ -745,20 +735,19 @@ void ContentWidget::onListViewRowChanged(SearchListView * listview, const int &t
* @param type
* @param path
*/
void ContentWidget::onListViewRowDoubleClicked(SearchListView * listview, const int &type, const QString &path)
{
qDebug()<<"A row has been double clicked.Type = "<<type<<"; Name = "<<path;
if (type == SearchItem::SearchType::Best && m_bestList.at(listview->currentIndex().row()).first != SearchItem::SearchType::Apps) {
void ContentWidget::onListViewRowDoubleClicked(SearchListView * listview, const int &type, const QString &path) {
qDebug() << "A row has been double clicked.Type = " << type << "; Name = " << path;
if(type == SearchItem::SearchType::Best && m_bestList.at(listview->currentIndex().row()).first != SearchItem::SearchType::Apps) {
m_detailView->doubleClickAction(m_bestList.at(listview->currentIndex().row()).first, path);
} else if (type == SearchItem::SearchType::Best && m_bestList.at(listview->currentIndex().row()).first == SearchItem::SearchType::Apps) {
if (m_appPathList.at(0) == "" || m_appPathList.at(0).isEmpty()){
} else if(type == SearchItem::SearchType::Best && m_bestList.at(listview->currentIndex().row()).first == SearchItem::SearchType::Apps) {
if(m_appPathList.at(0) == "" || m_appPathList.at(0).isEmpty()) {
m_detailView->doubleClickAction(SearchListView::ResType::App, m_appList.at(0));
} else {
m_detailView->doubleClickAction(SearchListView::ResType::App, m_appPathList.at(0));
}
} else if (type == SearchItem::SearchType::Apps) {
} else if(type == SearchItem::SearchType::Apps) {
int index = listview->currentIndex().row();
if (m_appPathList.at(index) == "" || m_appPathList.at(index).isEmpty()){
if(m_appPathList.at(index) == "" || m_appPathList.at(index).isEmpty()) {
m_detailView->doubleClickAction(SearchListView::ResType::App, m_appList.at(index));
} else {
m_detailView->doubleClickAction(SearchListView::ResType::App, m_appPathList.at(index));
@ -782,8 +771,7 @@ void ContentWidget::setContentList(const QStringList& list) {
* @brief ContentWidget::setKeyword
* @param keyword
*/
void ContentWidget::setKeyword(QString keyword)
{
void ContentWidget::setKeyword(QString keyword) {
m_keyword = keyword;
m_fileListView->setKeyword(keyword);
m_dirListView->setKeyword(keyword);
@ -798,15 +786,13 @@ void ContentWidget::setKeyword(QString keyword)
* @brief ContentWidget::setQuicklyOpenList
* @param list
*/
void ContentWidget::setQuicklyOpenList(const QStringList & list)
{
void ContentWidget::setQuicklyOpenList(const QStringList & list) {
m_quicklyOpenList = list;
}
/**
* @brief ContentWidget::closeWebView webview未关闭
*/
void ContentWidget::closeWebView()
{
void ContentWidget::closeWebView() {
m_detailView->closeWebWidget();
}

View File

@ -30,8 +30,7 @@
#include "show-more-label.h"
#include "title-label.h"
class ContentWidget : public QStackedWidget
{
class ContentWidget : public QStackedWidget {
Q_OBJECT
public:
ContentWidget(QWidget *);

View File

@ -19,18 +19,18 @@
*/
#include "config-file.h"
bool ConfigFile::writeCommonly(QString message){
QSettings *m_qSettings=new QSettings(HOMEPAGE_SETTINGS,QSettings::IniFormat);
QStringList messagelist=message.split("/");
QString appname=messagelist.last();
bool ConfigFile::writeCommonly(QString message) {
QSettings *m_qSettings = new QSettings(HOMEPAGE_SETTINGS, QSettings::IniFormat);
QStringList messagelist = message.split("/");
QString appname = messagelist.last();
if(!appname.contains("desktop"))
return false;
m_qSettings->beginGroup("Commonly");
QStringList quickly=m_qSettings->allKeys();
if(quickly.contains(message.mid(1, message.length()-1))){
m_qSettings->setValue(message,m_qSettings->value(message).toInt()+1);
}else{
m_qSettings->setValue(message,1);
QStringList quickly = m_qSettings->allKeys();
if(quickly.contains(message.mid(1, message.length() - 1))) {
m_qSettings->setValue(message, m_qSettings->value(message).toInt() + 1);
} else {
m_qSettings->setValue(message, 1);
}
m_qSettings->endGroup();
if(m_qSettings)
@ -38,26 +38,26 @@ bool ConfigFile::writeCommonly(QString message){
return true;
}
QStringList ConfigFile::readCommonly(){
QSettings *m_qSettings=new QSettings(HOMEPAGE_SETTINGS,QSettings::IniFormat);
QStringList ConfigFile::readCommonly() {
QSettings *m_qSettings = new QSettings(HOMEPAGE_SETTINGS, QSettings::IniFormat);
QStringList returnlist;
QMap<QString,int> quicklycount;
QMap<QString, int> quicklycount;
m_qSettings->beginGroup("Commonly");
QStringList Commonly=m_qSettings->allKeys();
for(int i=0;i<Commonly.size();i++){
quicklycount.insert(Commonly.at(i),m_qSettings->value(Commonly.at(i)).toInt());
QStringList Commonly = m_qSettings->allKeys();
for(int i = 0; i < Commonly.size(); i++) {
quicklycount.insert(Commonly.at(i), m_qSettings->value(Commonly.at(i)).toInt());
}
m_qSettings->endGroup();
QMap<QString, int>::iterator iter =quicklycount.begin();
QMap<QString, int>::iterator iter = quicklycount.begin();
QVector<QPair<QString, int>> vec;
while(iter !=quicklycount.end()) {
while(iter != quicklycount.end()) {
vec.push_back(qMakePair(iter.key(), iter.value()));
iter++;
}
qSort(vec.begin(), vec.end(), [](const QPair<QString, int> &l, const QPair<QString, int> &r) {
return (l.second > r.second);
});
for(int j=0;j<vec.size();j++){
for(int j = 0; j < vec.size(); j++) {
returnlist.append("/" + vec.at(j).first);
}
if(m_qSettings)
@ -65,22 +65,22 @@ QStringList ConfigFile::readCommonly(){
return returnlist.mid(0, 5);
}
bool ConfigFile::writeRecently(QString message){
QSettings *m_qSettings=new QSettings(HOMEPAGE_SETTINGS,QSettings::IniFormat);
bool ConfigFile::writeRecently(QString message) {
QSettings *m_qSettings = new QSettings(HOMEPAGE_SETTINGS, QSettings::IniFormat);
m_qSettings->beginGroup("Recently");
QStringList recently=m_qSettings->value("Recently").toStringList();
QStringList recently = m_qSettings->value("Recently").toStringList();
m_qSettings->endGroup();
if(recently.contains(message)){
if(recently.contains(message)) {
recently.removeOne(message);
}
recently.insert(0,message);
recently.insert(0, message);
m_qSettings->beginGroup("Recently");
if (m_qSettings->value("Recently").toStringList().length() >= 20) {
m_qSettings->setValue("Recently",QStringList(recently.mid(0, 20)));
if(m_qSettings->value("Recently").toStringList().length() >= 20) {
m_qSettings->setValue("Recently", QStringList(recently.mid(0, 20)));
} else {
m_qSettings->setValue("Recently",recently);
m_qSettings->setValue("Recently", recently);
}
m_qSettings->endGroup();
if(m_qSettings)
@ -88,34 +88,34 @@ bool ConfigFile::writeRecently(QString message){
return true;
}
QStringList ConfigFile::readRecently(){
QSettings *m_qSettings=new QSettings(HOMEPAGE_SETTINGS,QSettings::IniFormat);
QStringList ConfigFile::readRecently() {
QSettings *m_qSettings = new QSettings(HOMEPAGE_SETTINGS, QSettings::IniFormat);
m_qSettings->beginGroup("Recently");
QStringList recently=m_qSettings->value("Recently").toStringList();
QStringList recently = m_qSettings->value("Recently").toStringList();
m_qSettings->endGroup();
if(m_qSettings)
delete m_qSettings;
return recently.mid(0, 4);
}
bool ConfigFile::writeConfig(QString message){
bool ConfigFile::writeConfig(QString message) {
bool isWriteCommonlyDone = writeCommonly(message);
bool isWriteRecentlyDone = writeRecently(message);
return (isWriteCommonlyDone || isWriteRecentlyDone);
}
QMap<QString,QStringList> ConfigFile::readConfig(){
QMap<QString,QStringList> returnresult;
returnresult.insert("Commonly",readCommonly());
returnresult.insert("Recently",readRecently());
QMap<QString, QStringList> ConfigFile::readConfig() {
QMap<QString, QStringList> returnresult;
returnresult.insert("Commonly", readCommonly());
returnresult.insert("Recently", readRecently());
return returnresult;
}
void ConfigFile::receiveMessage(QString message){
void ConfigFile::receiveMessage(QString message) {
QFile file(HOMEPAGE_SETTINGS);
if(!file.exists()){
file.open( QIODevice::ReadWrite | QIODevice::Text );
if(!file.exists()) {
file.open(QIODevice::ReadWrite | QIODevice::Text);
file.close();
}
readConfig();//页面调用

View File

@ -26,18 +26,17 @@
#include <QFileInfo>
#include <QDir>
#define HOMEPAGE_SETTINGS QDir::homePath()+"/.config/org.ukui/ukui-search/ukui-search-homepage.conf"
class ConfigFile : public QObject
{
class ConfigFile : public QObject {
Q_OBJECT
public:
static bool writeConfig(QString message);
static QMap<QString,QStringList> readConfig();
static QMap<QString, QStringList> readConfig();
static void receiveMessage(QString message);
private:
static bool writeCommonly(QString message);
static QStringList readCommonly();
static bool writeRecently(QString message);
static QStringList readRecently();
static bool writeCommonly(QString message);
static QStringList readCommonly();
static bool writeRecently(QString message);
static QStringList readRecently();
};

View File

@ -22,14 +22,12 @@
#include <QIcon>
#include <QEvent>
FolderListItem::FolderListItem(QWidget *parent, const QString &path) : QWidget(parent)
{
FolderListItem::FolderListItem(QWidget *parent, const QString &path) : QWidget(parent) {
m_path = path;
initUi();
}
FolderListItem::~FolderListItem()
{
FolderListItem::~FolderListItem() {
}
@ -39,7 +37,7 @@ FolderListItem::~FolderListItem()
void FolderListItem::initUi() {
m_layout = new QVBoxLayout(this);
m_layout->setSpacing(0);
m_layout->setContentsMargins(0,0,0,0);
m_layout->setContentsMargins(0, 0, 0, 0);
m_widget = new QWidget(this);
m_widget->setObjectName("mWidget");
this->setFixedHeight(32);
@ -77,7 +75,7 @@ QString FolderListItem::getPath() {
* @brief FolderListItem::enterEvent
* @param event
*/
void FolderListItem::enterEvent(QEvent *event){
void FolderListItem::enterEvent(QEvent *event) {
m_delLabel->show();
m_widget->setStyleSheet("QWidget#mWidget{background: rgba(0,0,0,0.1);}");
QWidget::enterEvent(event);
@ -87,7 +85,7 @@ void FolderListItem::enterEvent(QEvent *event){
* @brief FolderListItem::leaveEvent
* @param event
*/
void FolderListItem::leaveEvent(QEvent *event){
void FolderListItem::leaveEvent(QEvent *event) {
m_delLabel->hide();
m_widget->setStyleSheet("QWidget#mWidget{background: transparent;}");
QWidget::leaveEvent(event);
@ -100,9 +98,9 @@ void FolderListItem::leaveEvent(QEvent *event){
* @param event
* @return
*/
bool FolderListItem::eventFilter(QObject *watched, QEvent *event){
if (watched == m_delLabel) {
if (event->type() == QEvent::MouseButtonPress) {
bool FolderListItem::eventFilter(QObject *watched, QEvent *event) {
if(watched == m_delLabel) {
if(event->type() == QEvent::MouseButtonPress) {
// qDebug()<<"pressed!";
Q_EMIT this->onDelBtnClicked(m_path);
}

View File

@ -26,8 +26,7 @@
#include <QVBoxLayout>
#include <QLabel>
class FolderListItem : public QWidget
{
class FolderListItem : public QWidget {
Q_OBJECT
public:
explicit FolderListItem(QWidget *parent = nullptr, const QString &path = 0);

View File

@ -27,8 +27,7 @@
#include <QAbstractTextDocumentLayout>
#include "global-settings.h"
HighlightItemDelegate::HighlightItemDelegate(QObject *parent) : QStyledItemDelegate (parent)
{
HighlightItemDelegate::HighlightItemDelegate(QObject *parent) : QStyledItemDelegate(parent) {
}
/**
@ -37,22 +36,21 @@ HighlightItemDelegate::HighlightItemDelegate(QObject *parent) : QStyledItemDeleg
* \param option
* \param index
*/
void HighlightItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
void HighlightItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const {
QStyleOptionViewItemV4 optionV4 = option;
initStyleOption(&optionV4, index);
QStyle *style = optionV4.widget? optionV4.widget->style() : QApplication::style();
QStyle *style = optionV4.widget ? optionV4.widget->style() : QApplication::style();
optionV4.text = QString();
style->drawControl(QStyle::CE_ItemViewItem, &optionV4, painter); //绘制非文本区域内容
if (index.model()->data(index,Qt::DisplayRole).toString().isEmpty()) return;
if(index.model()->data(index, Qt::DisplayRole).toString().isEmpty()) return;
QTextDocument doc;
doc.setHtml(getHtmlText(painter, option, index)); //提取富文本
QAbstractTextDocumentLayout::PaintContext ctx;
if (optionV4.state & QStyle::State_Selected)
if(optionV4.state & QStyle::State_Selected)
ctx.palette.setColor(QPalette::Text, optionV4.palette.color(QPalette::Active, QPalette::HighlightedText));
QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &optionV4);
@ -80,32 +78,31 @@ void HighlightItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem
* @param index
* @return
*/
QString HighlightItemDelegate::getHtmlText(QPainter *painter, const QStyleOptionViewItem &itemOption, const QModelIndex &index) const
{
QString HighlightItemDelegate::getHtmlText(QPainter *painter, const QStyleOptionViewItem &itemOption, const QModelIndex &index) const {
int indexFindLeft = 0;
QString indexString = index.model()->data(index,Qt::DisplayRole).toString();
QString indexString = index.model()->data(index, Qt::DisplayRole).toString();
QFont ft(painter->font().family(), GlobalSettings::getInstance()->getValue(FONT_SIZE_KEY).toInt());
QFontMetrics fm(ft);
QString indexColString = fm.elidedText(indexString, Qt::ElideRight, itemOption.rect.width() + 10); //当字体超过Item的长度时显示为省略号
// QFontMetrics m_QFontMetrics = painter->fontMetrics();
// QString indexColString = m_QFontMetrics.elidedText(indexString, Qt::ElideRight, itemOption.rect.width() + 10); //当字体超过Item的长度时显示为省略号
QString htmlString;
if ((indexColString.toUpper()).contains((m_regFindKeyWords.toUpper()))) {
if((indexColString.toUpper()).contains((m_regFindKeyWords.toUpper()))) {
indexFindLeft = indexColString.toUpper().indexOf(m_regFindKeyWords.toUpper()); //得到查找字体在当前整个Item字体中的位置
// paintKeywordHighlight(painter, itemOption, indexColString, indexFindLeft, m_regFindKeyWords.length());
htmlString = escapeHtml(indexColString.left(indexFindLeft)) + "<b>" + escapeHtml(indexColString.mid(indexFindLeft, m_regFindKeyWords.length())) + "</b>" + escapeHtml(indexColString.right(indexColString.length() - indexFindLeft - m_regFindKeyWords.length()));
} else {
bool boldOpenned = false;
for (int i = 0; i < indexColString.length(); i++) {
if ((m_regFindKeyWords.toUpper()).contains(QString(indexColString.at(i)).toUpper())) {
for(int i = 0; i < indexColString.length(); i++) {
if((m_regFindKeyWords.toUpper()).contains(QString(indexColString.at(i)).toUpper())) {
// paintKeywordHighlight(painter, itemOption, indexColString, i, 1);
if (! boldOpenned) {
if(! boldOpenned) {
boldOpenned = true;
htmlString.append(QString("<b>"));
}
htmlString.append(escapeHtml(QString(indexColString.at(i))));
} else {
if (boldOpenned) {
if(boldOpenned) {
boldOpenned = false;
htmlString.append(QString("</b>"));
}
@ -123,8 +120,7 @@ QString HighlightItemDelegate::getHtmlText(QPainter *painter, const QStyleOption
* @param str
* @return
*/
QString HighlightItemDelegate::escapeHtml(const QString & str) const
{
QString HighlightItemDelegate::escapeHtml(const QString & str) const {
QString temp = str;
temp.replace("<", "&lt;");
temp.replace(">", "&gt;");
@ -139,8 +135,7 @@ QString HighlightItemDelegate::escapeHtml(const QString & str) const
* @param indexFindLeft
* @param keywordLength
*/
void HighlightItemDelegate::paintKeywordHighlight(QPainter *painter, const QStyleOptionViewItem &itemOption, const QString &indexColString, const int &indexFindLeft, const int &keywordLength) const
{
void HighlightItemDelegate::paintKeywordHighlight(QPainter *painter, const QStyleOptionViewItem &itemOption, const QString &indexColString, const int &indexFindLeft, const int &keywordLength) const {
QPen pen(Qt::black);
painter->setPen(pen);
QFont font = QApplication::font(itemOption.widget);
@ -157,15 +152,14 @@ void HighlightItemDelegate::paintKeywordHighlight(QPainter *painter, const QStyl
QStyle * m_QStyle = m_QWidget ? m_QWidget->style() : QApplication::style(); //得到当前的style
QRect m_QRect = itemOption.rect;//得到Item的自己的Rect
QPalette::ColorRole textDisplayRole = QPalette::NoRole; //设置text的role
if (itemOption.state & QStyle::State_Selected)
{
if(itemOption.state & QStyle::State_Selected) {
textDisplayRole = QPalette::HighlightedText; //当选中字体的时候字体显示高亮
} else {
textDisplayRole = QPalette::Text;
}
int findKeyWordWidth = m_leftFontMetrics.width(m_regFindKeyWords); //得到查找字体的像素宽度
int preFindKeyWordWidth = m_leftFontMetrics.width(indexColString.mid(0,indexFindLeft)); //得到查找字体前面的字体的像素宽度
int preFindKeyWordWidth = m_leftFontMetrics.width(indexColString.mid(0, indexFindLeft)); //得到查找字体前面的字体的像素宽度
m_QRect = m_QRect.adjusted(preFindKeyWordWidth + 3, 0, findKeyWordWidth, 0);
//高亮字段
@ -177,8 +171,7 @@ void HighlightItemDelegate::paintKeywordHighlight(QPainter *painter, const QStyl
* \brief treewidget_styledItemDelegate::search_keyword
* \param regFindKeyWords
*/
void HighlightItemDelegate::setSearchKeyword(const QString &regFindKeyWords)
{
void HighlightItemDelegate::setSearchKeyword(const QString &regFindKeyWords) {
m_regFindKeyWords.clear();
m_regFindKeyWords = regFindKeyWords;
}

View File

@ -23,15 +23,14 @@
#include <QStyledItemDelegate>
class HighlightItemDelegate : public QStyledItemDelegate
{
class HighlightItemDelegate : public QStyledItemDelegate {
Q_OBJECT
public:
explicit HighlightItemDelegate(QObject *parent = nullptr);
void setSearchKeyword(const QString &);
private:
QString m_regFindKeyWords = 0;
void paint(QPainter *,const QStyleOptionViewItem &, const QModelIndex &) const override;
void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const override;
QString getHtmlText(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const;
QString escapeHtml(const QString&) const;
void paintKeywordHighlight(QPainter *, const QStyleOptionViewItem &, const QString &, const int &, const int &) const;

View File

@ -28,14 +28,13 @@
#include <QUrl>
#include <QApplication>
HomePageItem::HomePageItem(QWidget *parent, const int& type, const QString& path) : QWidget(parent)
{
HomePageItem::HomePageItem(QWidget *parent, const int& type, const QString& path) : QWidget(parent) {
setupUi(type, path);
m_transparency = 0.06;
connect(qApp, &QApplication::paletteChanged, this, [ = ]() {
if (m_namelabel) {
if(m_namelabel) {
QString name = this->toolTip();
if (m_type == ItemType::Recent) {
if(m_type == ItemType::Recent) {
m_namelabel->setText(m_namelabel->fontMetrics().elidedText(name, Qt::ElideRight, 250));
} else {
m_namelabel->setText(m_namelabel->fontMetrics().elidedText(name, Qt::ElideRight, 108));
@ -44,8 +43,7 @@ HomePageItem::HomePageItem(QWidget *parent, const int& type, const QString& path
});
}
HomePageItem::~HomePageItem()
{
HomePageItem::~HomePageItem() {
}
/**
@ -62,42 +60,42 @@ void HomePageItem::setupUi(const int& type, const QString& path) {
m_widget->installEventFilter(this);
m_iconlabel = new QLabel(m_widget);
m_namelabel = new QLabel(m_widget);
if (type == ItemType::Recent) {
if(type == ItemType::Recent) {
m_widget->setFixedSize(300, 48);
QIcon icon;
switch (SearchListView::getResType(path)) { //可能出现文件应用等,需要根据路径判断类型
case SearchListView::ResType::App : {
icon = FileUtils::getAppIcon(path);
m_namelabel->setText(FileUtils::getAppName(path));
QFontMetrics fontMetrics = m_namelabel->fontMetrics();
QString name = FileUtils::getAppName(path);
m_namelabel->setText(fontMetrics.elidedText(name, Qt::ElideRight, 250));
this->setToolTip(name);
break;
}
case SearchListView::ResType::Best :
case SearchListView::ResType::Content:
case SearchListView::ResType::Dir :
case SearchListView::ResType::File : {
icon = FileUtils::getFileIcon(QString("file://%1").arg(path));
switch(SearchListView::getResType(path)) { //可能出现文件应用等,需要根据路径判断类型
case SearchListView::ResType::App : {
icon = FileUtils::getAppIcon(path);
m_namelabel->setText(FileUtils::getAppName(path));
QFontMetrics fontMetrics = m_namelabel->fontMetrics();
QString name = FileUtils::getAppName(path);
m_namelabel->setText(fontMetrics.elidedText(name, Qt::ElideRight, 250));
this->setToolTip(name);
break;
}
case SearchListView::ResType::Best :
case SearchListView::ResType::Content:
case SearchListView::ResType::Dir :
case SearchListView::ResType::File : {
icon = FileUtils::getFileIcon(QString("file://%1").arg(path));
// m_namelabel->setText(FileUtils::getFileName(path));
QFontMetrics fontMetrics = m_namelabel->fontMetrics();
QString name = FileUtils::getFileName(path);
m_namelabel->setText(fontMetrics.elidedText(name, Qt::ElideRight, 250));
this->setToolTip(name);
break;
}
case SearchListView::ResType::Setting : {
icon = FileUtils::getSettingIcon(path, true);
QFontMetrics fontMetrics = m_namelabel->fontMetrics();
QString name = FileUtils::getFileName(path);
m_namelabel->setText(fontMetrics.elidedText(name, Qt::ElideRight, 250));
this->setToolTip(name);
break;
}
case SearchListView::ResType::Setting : {
icon = FileUtils::getSettingIcon(path, true);
// m_namelabel->setText(FileUtils::getSettingName(path));
QFontMetrics fontMetrics = m_namelabel->fontMetrics();
QString name = FileUtils::getSettingName(path);
m_namelabel->setText(fontMetrics.elidedText(name, Qt::ElideRight, 250));
this->setToolTip(name);
break;
}
default :
break;
QFontMetrics fontMetrics = m_namelabel->fontMetrics();
QString name = FileUtils::getSettingName(path);
m_namelabel->setText(fontMetrics.elidedText(name, Qt::ElideRight, 250));
this->setToolTip(name);
break;
}
default :
break;
}
m_iconlabel->setPixmap(icon.pixmap(icon.actualSize(QSize(24, 24))));
m_hlayout = new QHBoxLayout(m_widget);
@ -107,12 +105,12 @@ void HomePageItem::setupUi(const int& type, const QString& path) {
m_hlayout->addWidget(m_namelabel);
m_hlayout->addStretch();
return;
} else if (type == ItemType::Quick) {
QIcon icon = FileUtils::getAppIcon(path);
m_iconlabel->setPixmap(icon.pixmap(icon.actualSize(QSize(48, 48))));
QString name = FileUtils::getAppName(path);
m_namelabel->setText(m_namelabel->fontMetrics().elidedText(name, Qt::ElideRight, 108));
this->setToolTip(name);
} else if(type == ItemType::Quick) {
QIcon icon = FileUtils::getAppIcon(path);
m_iconlabel->setPixmap(icon.pixmap(icon.actualSize(QSize(48, 48))));
QString name = FileUtils::getAppName(path);
m_namelabel->setText(m_namelabel->fontMetrics().elidedText(name, Qt::ElideRight, 108));
this->setToolTip(name);
} else {
QIcon icon = FileUtils::getAppIcon(path);
m_iconlabel->setPixmap(icon.pixmap(icon.actualSize(QSize(48, 48))));
@ -124,56 +122,55 @@ void HomePageItem::setupUi(const int& type, const QString& path) {
}
m_widget->setFixedSize(116, 116);
m_vlayout = new QVBoxLayout(m_widget);
m_vlayout->setContentsMargins(0,16,0,12);
m_vlayout->setContentsMargins(0, 16, 0, 12);
m_iconlabel->setAlignment(Qt::AlignCenter);
m_namelabel->setAlignment(Qt::AlignCenter);
m_vlayout->addWidget(m_iconlabel);
m_vlayout->addWidget(m_namelabel);
}
void HomePageItem::onItemClicked()
{
switch (SearchListView::getResType(m_path)) {
case SearchListView::ResType::App: {
GDesktopAppInfo * desktopAppInfo = g_desktop_app_info_new_from_filename(m_path.toLocal8Bit().data());
g_app_info_launch(G_APP_INFO(desktopAppInfo),nullptr, nullptr, nullptr);
g_object_unref(desktopAppInfo);
break;
}
case SearchListView::ResType::Best:
case SearchListView::ResType::Content:
case SearchListView::ResType::Dir:
case SearchListView::ResType::File: {
QDesktopServices::openUrl(QUrl::fromLocalFile(m_path));
break;
}
case SearchListView::ResType::Setting: {
//打开控制面板对应页面
QProcess process;
process.startDetached(QString("ukui-control-center --%1").arg(m_path.left(m_path.indexOf("/")).toLower()));
break;
}
default:
break;
void HomePageItem::onItemClicked() {
switch(SearchListView::getResType(m_path)) {
case SearchListView::ResType::App: {
GDesktopAppInfo * desktopAppInfo = g_desktop_app_info_new_from_filename(m_path.toLocal8Bit().data());
g_app_info_launch(G_APP_INFO(desktopAppInfo), nullptr, nullptr, nullptr);
g_object_unref(desktopAppInfo);
break;
}
case SearchListView::ResType::Best:
case SearchListView::ResType::Content:
case SearchListView::ResType::Dir:
case SearchListView::ResType::File: {
QDesktopServices::openUrl(QUrl::fromLocalFile(m_path));
break;
}
case SearchListView::ResType::Setting: {
//打开控制面板对应页面
QProcess process;
process.startDetached(QString("ukui-control-center --%1").arg(m_path.left(m_path.indexOf("/")).toLower()));
break;
}
default:
break;
}
}
bool HomePageItem::eventFilter(QObject *watched, QEvent *event){
if (watched == m_widget){
if (event->type() == QEvent::MouseButtonPress) {
bool HomePageItem::eventFilter(QObject *watched, QEvent *event) {
if(watched == m_widget) {
if(event->type() == QEvent::MouseButtonPress) {
m_transparency = 0.06;
this->update();
return true;
} else if (event->type() == QEvent::MouseButtonRelease) {
} else if(event->type() == QEvent::MouseButtonRelease) {
this->onItemClicked();
m_transparency = 0.06;
this->update();
return true;
} else if (event->type() == QEvent::Enter) {
} else if(event->type() == QEvent::Enter) {
m_transparency = 0.15;
this->update();
return true;
} else if (event->type() == QEvent::Leave) {
} else if(event->type() == QEvent::Leave) {
m_transparency = 0.06;
this->update();
return true;

View File

@ -28,8 +28,7 @@
#include "file-utils.h"
#include "search-list-view.h"
class HomePageItem : public QWidget
{
class HomePageItem : public QWidget {
Q_OBJECT
public:
explicit HomePageItem(QWidget *, const int&, const QString&);

Some files were not shown because too many files have changed in this diff Show More