4

我在 stl 容器(向量)中有数据。向量中的每个节点都是一个结构,其中还包含 stl 字符串。

struct record
{
string name;
string location;
int salary;
}

vector< record > employees;

我想序列化员工,但我也想在序列化之前对其进行加密。

我的加密功能如下所示:

Encode(const char * inBfr, const int in_size, char ** outBfr, int& out_size )

通过搜索,stl 标准似乎不需要我的结构的内存是连续的,所以我不能只抓取employees变量的内存。有没有其他智能方法可以将此编码功能与基于 stl 的结构/容器一起使用?Encode 函数在普通的 char * 缓冲区中工作对我有好处,所以我确切地知道进出的内容,但 stl 结构不是,我正在努力寻找一种好方法,以便我可以将 stl 与此函数一起使用。

如果有帮助,我也愿意使用任何其他 stl 容器。

4

2 回答 2

12

尽管std::vector<T>保证中的元素是连续布局的,但这并没有真正的帮助:您拥有的记录可能包括填充,更重要的是,将存储对象std::string外部的内容std::string(如果小字符串优化是使用时,该值可以嵌入到内部,std::string但它也将包含几个不属于std::strings 值的字节)。因此,您最好的选择是格式化您的记录并加密格式化的字符串。

格式化很简单,但我个人会将编码函数封装成一个简单的函数std::streambuf,以便加密可以通过过滤流缓冲区完成。鉴于您给出的签名,这可能看起来像这样:

class encryptbuf
    : public std::streambuf {
    std::streambuf* d_sbuf;
    char            d_buffer[1024];
public:
    encryptbuf(std::streambuf* sbuf)
        : d_sbuf(sbuf) {
        this->setp(this->d_buffer, this->d_buffer + sizeof(this->d_buffer) - 1);
    }
    int overflow(int c) {
        if (c != std::char_traits<char>::eof()) {
            *this->pptr() = std::char_traits<char>::to_char_type(c);
            this->pbump(1);
        }
        return this->pubsync()? std::char_traits<char>::eof(): std::char_traits<char>::not_eof(c);
    }
    int sync() {
        char* out(0);
        int   size(0);
        Encode(this->pbase(), this->pptr() - this->pbase(), &out, size);
        this->d_sbuf->sputn(out, size);
        delete[] out; // dunno: it seems the output buffer is allocated but how?
        this->setp(this->pbase(), this->epptr());
        return this->d_sbuf->pubsync();
    }
};

int main() {
    encryptbuf    sbuf(std::cout.rdbuf());
    std::ostream eout(&sbuf);
    eout << "print something encoded to standard output\n" << std::flush;
}

现在,为您的记录创建一个输出运算符,只需打印到一个std::ostream可用于创建一个编码

于 2012-10-03T21:59:11.710 回答
6

将您的结构序列化为字符串,然后加密字符串可能是最简单的。例如:

std::ostringstream buffer;

buffer << a_record.name << "\n" << a_record.location << "\n" << a_record.salary;

encode(buffer.str().c_str(), buffer.str().length(), /* ... */);

如果是我,我可能会编写encode(或至少是它的包装器)以在向量、字符串或流中获取输入(并可能产生输出)。

如果你想变得雄心勃勃,还有其他可能性。首先,@MooingDuck 提出了一个很好的观点,即通常值得operator<<为班级重载,而不是一直处理单个项目。这通常是一个类似于上面的小函数:

std::ostream &operator<<(std::ostream &os, record const &r) { 
    return os << r.name << "\n" << r.location << "\n" << r.salary;
}

使用它,您只需:

std::ostringstream os;
os << a_record;

encode(os.str().c_str(), os.str().length(), /* ... */);

其次,如果你想变得更加雄心勃勃,你可以将加密放入(例如)一个codecvt方面,这样你就可以在将所有数据写入流时自动加密,并在读回时对其进行解密。另一种可能性是将加密构建到过滤streambuf对象中。codecvt方面可能是理论上应该首选的方法,但几乎可以肯定的是streambuf更容易实现,涉及的不相关“东西”更少。

于 2012-10-03T21:14:44.980 回答