📄 delimited_file.cpp
字号:
/**********************************************************************************
* *
* Copyright (c) 2003 - 2004 by Royal. All rights reserved. *
* *
* Permission to use, copy, modify, and distribute this software for any purpose *
* is hereby granted without fee, provided that this copyright and permissions *
* notice appear in all copies and derivatives, and that no charge may be made *
* for the software and its documentation except to cover cost of distribution. *
* *
* This software is provided "as is" without express or implied warranty. *
* *
**********************************************************************************/
/*
* Description:
*
* Implementation of class Delimited_file.
*
* History:
*
* Initial version created by Royal, January 2003.
* Updated it by Royal, Feb 2004.
*
* Notes:
*
* This code has been written to conform to standard C++ and STL. It has been
* compiled successfully using GNU C++ 3.2, Borland C++ 5.5, and Visual C++ 7.0.
*/
#include "delimited_file.h"
using namespace std;
namespace dragon
{
Delimited_file::Delimited_file(const string& file_name, const string& separator, bool backup):
file_name_(file_name), separator_(separator), backup_(backup)
{
transaction_ = false;
row_total_count_ = 0;
col_total_count_ = 0;
current_row_ = 0;
if (open())
{
if (backup_)
{
string fn, fb;
fn = file_name_;
fb = file_name_ + ".bak";
file_name_ = fb;
if (!commit()) backup_ = false;
file_name_ = fn;
}
}
}
Delimited_file::~Delimited_file()
{
}
bool Delimited_file::initial_col_headers(const vector<string>& value)
{
if (row_total_count_ >= 1)
{
last_error_ = err_col_initial_already;
return false;
}
col_headers_.clear();
col_headers_.assign(value.begin(), value.end());
rows_.push_back(delimit(value));
col_total_count_ = value.size();
++row_total_count_;
++current_row_;
if (!transaction_) commit();
return true;
}
bool Delimited_file::insert_row(const vector<string>& value, size_t row)
{
if (!is_row_in_range(row))
{
last_error_ = err_row_out_of_range;
return false;
}
if (value.size() != col_total_count_)
{
last_error_ = err_row_size_error;
return false;
}
if (row == 1)
{
col_headers_.clear();
col_headers_.assign(value.begin(), value.end());
}
rows_.insert(rows_.begin() + row -1, delimit(value));
++row_total_count_;
++current_row_;
if (!transaction_) commit();
return true;
}
bool Delimited_file::update_row(const vector<string>& value, size_t row)
{
if (!is_row_in_range(row))
{
last_error_ = err_row_out_of_range;
return false;
}
if (value.size() != col_total_count_)
{
last_error_ = err_row_size_error;
return false;
}
if (row == 1)
{
col_headers_.clear();
col_headers_.assign(value.begin(), value.end());
}
rows_[row-1] = delimit(value);
if (!transaction_) commit();
return true;
}
bool Delimited_file::delete_row(size_t row)
{
if (!is_row_in_range(row))
{
last_error_ = err_row_out_of_range;
return false;
}
rows_.erase(rows_.begin() + row -1);
--row_total_count_;
--current_row_;
if (!transaction_) commit();
return true;
}
bool Delimited_file::read_row(vector<string>& value, size_t row)
{
if (!is_row_in_range(row))
{
last_error_ = err_row_out_of_range;
return false;
}
value.clear();
current_row_ = row;
string ts = rows_[current_row_-1];
++current_row_;
string dv = "\"" + separator_ + "\"";
string::size_type sep_pos = ts.find(dv);
if (sep_pos != string::npos)
{
string::size_type count, start_pos(0);
while (sep_pos != string::npos)
{
count = sep_pos - start_pos;
value.push_back(ts.substr(start_pos, count));
start_pos = sep_pos + dv.length();
sep_pos = ts.find(dv, start_pos);
}
count = ts.length() - start_pos;
value.push_back(ts.substr(start_pos, count));
// remove " before the first col
ts = value[0];
ts.erase(0, 1);
value[0] = ts;
// remove " after the last col
ts = value[value.size()-1];
ts.erase(ts.length()-1, 1);
value[value.size()-1] = ts;
return true;
}
last_error_ = err_fail_to_read_row;
return false;
}
bool Delimited_file::append_row(const vector<string>& value)
{
if (value.size() != col_total_count_)
{
last_error_ = err_row_size_error;
return false;
}
rows_.push_back(delimit(value));
++current_row_;
++row_total_count_;
if (!transaction_) commit();
return true;
}
bool Delimited_file::update_rows(const vector<string>& value, size_t col, string condition,
bool only_first)
{
if (!is_col_in_range(col))
{
last_error_ = err_col_out_of_range;
return false;
}
bool tran = transaction_;
transaction_ = true;
vector<string> tv;
for (size_t i = 1; i <= row_total_count_; ++i)
{
read_row(tv, i);
if (tv.size() != col_total_count_)
{
transaction_ = tran;
last_error_ = err_row_size_error;
return false;
}
if (tv[col - 1] == condition)
{
update_row(value, i);
if (only_first) return true;
}
}
transaction_ = tran;
if (!transaction_) commit();
return true;
}
bool Delimited_file::update_rows(const vector<string>& value, string col, string condition,
bool only_first)
{
size_t col_index = get_col_no(col);
return update_rows(value, col_index, condition, only_first);
}
bool Delimited_file::delete_rows(size_t col, const string& condition, bool only_first)
{
if (!is_col_in_range(col))
{
last_error_ = err_col_out_of_range;
return false;
}
bool tran = transaction_;
transaction_ = true;
vector<string> tv;
for (size_t i = 1; i <= row_total_count_; ++i)
{
read_row(tv, i);
if (tv.size() != col_total_count_)
{
transaction_ = tran;
last_error_ = err_row_size_error;
return false;
}
if (tv[col - 1] == condition)
{
delete_row(i);
--i; // be careful! because row_total_count_ minus 1
if (only_first) return true;
}
}
transaction_ = tran;
if (!transaction_) commit();
return true;
}
bool Delimited_file::delete_rows(const string& col, const string& condition, bool only_first)
{
size_t col_index = get_col_no(col);
return delete_rows(col_index, condition, only_first);
}
bool Delimited_file::read_row(vector<string>& value, size_t col, const string& condition)
{
if (!is_col_in_range(col))
{
last_error_ = err_col_out_of_range;
return false;
}
for (size_t i = 1; i <= row_total_count_; ++i)
{
read_row(value, i);
if (value.size() != col_total_count_)
{
last_error_ = err_row_size_error;
return false;
}
if (value[col - 1] == condition) return true;
}
value.clear(); // clear used elements that could be read by the last read_row.
return false;
}
bool Delimited_file::read_row(vector<string>& value, const string& col, const string& condition)
{
size_t col_index = get_col_no(col);
return read_row(value, col_index, condition);
}
bool Delimited_file::read_rows(vector<vector<string> >& values, size_t col, const string& condition)
{
if (!is_col_in_range(col))
{
last_error_ = err_col_out_of_range;
return false;
}
vector<string> tv;
for (size_t i = 1; i <= row_total_count_; ++i)
{
read_row(tv, i);
if (tv.size() != col_total_count_)
{
last_error_ = err_row_size_error;
return false;
}
if (tv[col - 1] == condition) values.push_back(tv);
}
return true;
}
bool Delimited_file::read_rows(vector<vector<string> >& values, const string& col,
const string& condition)
{
size_t col_index = get_col_no(col);
if (!is_col_in_range(col_index))
{
last_error_ = err_col_out_of_range;
return false;
}
return read_rows(values, col_index, condition);
}
bool Delimited_file::append_col(const string& name, const string& value)
{
bool tran = transaction_;
transaction_ = true;
vector<string> tv;
for (size_t i = 1; i <= row_total_count_; ++i)
{
if(tv.size() != col_total_count_)
{
transaction_ = tran;
last_error_ = err_row_size_error;
return false;
}
if(i == 1)
{
tv.push_back(name);
col_headers_.clear();
col_headers_.assign(tv.begin(), tv.end());
++col_total_count_;
}
else tv.push_back(value);
update_row(tv, i);
}
transaction_ = tran;
if (!transaction_) commit();
return true;
}
bool Delimited_file::insert_col(const string& name, size_t col, const string& value)
{
if (!is_col_in_range(col))
{
last_error_ = err_col_out_of_range;
return false;
}
bool tran = transaction_;
transaction_ = true;
// should be placed here, otherwise the later update_row would be disturbed.
++col_total_count_;
for (size_t i = 1; i <= row_total_count_; ++i)
{
vector<string> tv;
read_row(tv, i);
vector<string>::iterator pos;
pos = tv.begin() + col - 1;
if (i == 1)
{
tv.insert(pos, name);
col_headers_.clear();
col_headers_.assign(tv.begin(), tv.end());
}
else tv.insert(pos, value);
update_row(tv, i);
}
transaction_ = tran;
if (!transaction_) commit();
return true;
}
bool Delimited_file::insert_col(const string& name, const string& col, const string& value)
{
size_t col_index = get_col_no(col);
return insert_col(name, col_index, value);
}
bool Delimited_file::update_col(size_t col, const string& value)
{
if (!is_col_in_range(col))
{
last_error_ = err_col_out_of_range;
return false;
}
bool tran = transaction_;
transaction_ = true;
vector<string> tv;
// do not update the col header. so i = 2...
for (size_t i = 2; i <= row_total_count_; ++i)
{
read_row(tv, i);
if (tv.size() != col_total_count_)
{
transaction_ = tran;
last_error_ = err_row_size_error;
return false;
}
tv[col-1] = value;
update_row(tv, i);
}
transaction_ = tran;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -