从零开始实现自己的httpd——buffer

准备工作

ANSI C标准中有几个标准预定义宏(也是常用的):

__LINE__:在源代码中插入当前源代码行号;

__FILE__:在源文件中插入当前源文件名;

__DATE__:在源文件中插入当前的编译日期

__TIME__:在源文件中插入当前编译时间;

__STDC__:当要求程序严格遵循ANSI C标准时该标识被赋值为1;

__cplusplus:当编写C++程序时该标识符被定义。

编译器在进行源码编译的时候,会自动将这些宏替换为相应内容。

Log.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

#ifndef __LOG_H__
#define __LOG_H__

#include <string.h>

#include <cerrno>
#include <iostream>
#include <system_error>

#define __STR(s) #s
#define WHERE __STR(__FILE__ ":" __LINE__)

#define _E(msg) \
std::cerr << "[ERROR] " << __FILE__ << ":" << __LINE__ << " " << msg << std::endl;

#define _W(msg) \
std::cerr << "[WARNING] " << __FILE__ << ":" << __LINE__ << " " << msg << std::endl;

#define _I(msg) \
std::cerr << "[INFO] " << msg << std::endl;

#define SYSTEM_ERROR() \
do { \
_E(strerror(errno));\
} while (0)

#define THROW_SYSTEM_ERROR() \
do { \
SYSTEM_ERROR(); \
throw std::system_error(std::error_code(errno, std::system_category()));\
} while (0)

#define SYSTEM_WARNING() \
do { \
_W(strerror(errno)) \
} while (0)

#define THROW(msg) \
do { \
throw std::runtime_error(msg);\
} while (0)

#endif /* __LOG_H__ */

Buffer.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

#ifndef __BUFFER_H__
#define __BUFFER_H__

#include <stdlib.h>

#include "Log.h"

template<typename T>
class Buffer
{
public:
Buffer(size_t capacity = 1024) : capacity(capacity) , size(0) {
if (capacity == 0) {
data = nullptr;
return;
}

data = reinterpret_cast<T*>(malloc(capacity * sizeof(T)));
if (!data) {
THROW_SYSTEM_ERROR();
}
}

~Buffer() {
if (data) {
free(data);
}
}

size_t size() const {
return size;
}

size_t capacity() const {
return capacity;
}

void setCapacity(size_t _capacity) {
capacity = capacity;
errno = 0;
data = reinterpret_cast<T*>(
realloc(data, capacity * sizeof(T)));
if (errno) {
THROW_SYSTEM_ERROR();
}
}

void append(const T *src, size_t _size) {
if (capacity < size + _size) {
setCapacity(capacity + size);
}

if (src >= data && src < data + capacity) {
_E("src and dst do ovelap")
}
memcpy(data + size, src, _size);

size += _size;
}

void drain(size_t n) {
if (n == 0)
return;

if (n > size) {
THROW("not enough data");
}

size_t count = size - n;
T *ptr1 = data;
T *ptr2 = data + n;

while (count) {
size_t count2 = std::min(n, count);

memcpy(ptr1, ptr2, count2);
ptr1 = ptr2;
ptr2 += count2;
count -= count2;
}

size -= n;
}

const T* data() {
return data;
}

private:
T* data;
size_t capacity;
size_t size;
};

#endif
文章目录