//-----------------------------------.h---------------------------------------
#ifndef MYSERIALIZATION_H
#define MYSERIALIZATION_H
#include <memory>
#include <vector>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <nghttp2/nghttp2.h>
#define MAKE_NV(K, V) \
{ \
(uint8_t *)K, (uint8_t *)V, sizeof(K) - 1, sizeof(V) - 1, \
NGHTTP2_NV_FLAG_NONE \
}
class Deflate
{
public:
Deflate() : def(nullptr), errorCode(0) {}
~Deflate()
{
free();
}
nghttp2_hd_deflater* getDef()
{
if(!def)
{
errorCode = nghttp2_hd_deflate_new(&def, 4096);
if(0 != errorCode)
{
def = nullptr;
}
printf("nghttp2_hd_deflate_new %d\n", errorCode);
}
return def;
}
void free()
{
//必须跟inflater配套使用,否则每次都要创建新的deflate
if(def)
{
nghttp2_hd_deflate_del(def);
def = nullptr;
printf("nghttp2_hd_deflate_del\n");
}
}
int getErrorcode()
{
return errorCode;
}
private:
nghttp2_hd_deflater* def;
int errorCode;
};
class mySerialization
{
public:
mySerialization();
template <typename T, size_t N>
int httpSerialization(T nva[N]);
void test();
private:
std::vector<uint8_t> output;
static Deflate def;
};
#endif
//-----------------------------------.cpp---------------------------------------
#include "mySerialization.h"
Deflate mySerialization::def;
void mySerialization::test()
{
nghttp2_nv nva[5] = {
MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "example.org"),
MAKE_NV(":path", "/"), MAKE_NV("user-agent", "libnghttp2"),
MAKE_NV("accept-encoding", "gzip, deflate")};
httpSerialization<nghttp2_nv, sizeof(nva)/sizeof(nva[0])>(nva);
uint8_t comp[] = {0x87, 0x41, 0x88, 0x2F, 0x91, 0xD3, 0x5D, 0x05, 0x5C, 0xF6, 0x4D, 0x84, 0x7A, 0x87, 0xA0, 0xD1, 0xD5, 0x34, 0xE9, 0x4D, 0x62, 0x90};
for(int i = 0; i < output.size(); i++)
{
if(output[i] != comp[i])
{
printf("Failed: %d [%x] [%x]\n", i, output[i], comp[i]);
return;
}
}
def.free();
std::cout << "Success" << std::endl;
}
mySerialization::mySerialization() : output()
{
output.reserve(1024);
}
template <typename T, size_t N>
int mySerialization::httpSerialization(T nva[N])
{
int result = 0;
int buflen = 0;
do
{
if(N <= 0){ result = 1; }
nghttp2_hd_deflater* deflater = def.getDef();
if(def.getErrorcode() > 0)
{
result = def.getErrorcode();
break;
}
buflen = nghttp2_hd_deflate_bound(deflater, nva, N);
std::unique_ptr<uint8_t> buf(new uint8_t(buflen));
result = nghttp2_hd_deflate_hd(deflater, buf.get(), buflen, nva, N);
if(result < 0) { break; }
for(int i = 0; i < result; i++)
{
output.emplace_back(buf.get()[i]);
}
} while (false);
return result;
}