forked from sysrun/embencode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEmBencode.h
133 lines (111 loc) · 4.09 KB
/
EmBencode.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/// @file
/// Embedded bencode support, header definitions.
// 2012-09-29 <[email protected]> http://opensource.org/licenses/mit-license.php
#ifndef EmBencode_h
#define EmBencode_h
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
/// Encoder class to generate Bencode on the fly (no buffer storage needed).
class EmBencode {
public:
EmBencode () {}
/// Push a string out in Bencode format.
/// @param str The zero-terminated string to send out (without trailing \0).
void push (const char* str) {
push(str, strlen(str));
}
/// Push arbitrary bytes in Bencode format.
/// @param ptr Pointer to the data to send out.
/// @param len Number of data bytes to send out.
void push (const void* ptr, uint8_t len) {
PushCount(len);
PushChar(':');
PushData(ptr, len);
}
/// Push a signed integer in Bencode format.
/// @param val The integer to send (this implementation supports 32 bits).
void push (long val) {
PushChar('i');
if (val < 0) {
PushChar('-');
val = -val;
}
PushCount(val);
PushEnd();
}
/// Start a new new list. Must be matched with a call to endList().
/// Entries can be nested with more calls to startList(), startDict(), etc.
void startList () {
PushChar('l');
}
/// Terminate a list, started earlier with a call to startList().
void endList () {
PushEnd();
}
/// Start a new new dictionary. Must be matched with a call to endDict().
/// Dictionary entries must consist of a string key plus an arbitrary value.
/// Entries can be nested with more calls to startList(), startDict(), etc.
void startDict () {
PushChar('d');
}
/// Terminate a dictionary, started earlier with a call to startDict().
void endDict () {
PushEnd();
}
protected:
//Works
void PushCount (uint32_t num) {
char buf[11] = {};
ultoa(num, buf, 10);
PushData(buf, strlen(buf));
}
//doesn't work always
// void PushCount (uint32_t num) {
// char buf[11];
// PushData(ultoa(num, buf, 10), strlen(buf));
// }
void PushEnd () {
PushChar('e');
}
void PushData (const void* ptr, uint8_t len) {
for (const char* p = (const char*) ptr; len-- > 0; ++p)
PushChar(*p);
}
/// This function is not implemented in the library. It must be supplied by the caller
/// or inherited from `EmBencode` to implement the actual writing of characters.
// Fix Undefined symbols for architecture x86_64: "typeinfo for EmBencode", referenced from: typeinfo for BERadioEncoder in generic-f4c730.o
// https://stackoverflow.com/questions/307352/g-undefined-reference-to-typeinfo/307381#307381
virtual void PushChar (char ch);
};
/// Decoder class, needs an external buffer to collect the incoming data.
class EmBdecode {
public:
/// Types of tokens, as returned by nextToken().
enum { T_STRING = 0, T_NUMBER = 251, T_DICT, T_LIST, T_POP, T_END };
/// Initialize a decoder instance with the specified buffer space.
/// @param buf Pointer to the buffer which will be used by the decoder.
/// @param len Size of the buffer, must be in the range 50 to 255.
EmBdecode (char* buf, uint8_t len)
: bufPtr (buf), bufLen (len) { reset(); }
/// Reset the decoder - can be called to prepare for a new round of decoding.
uint8_t reset ();
/// Process a single incoming caharacter.
/// @return Returns a count > 0 when the buffer contains a complete packet.
uint8_t process (char ch);
/// Call this after process() is done, to extract each of the data tokens.
/// @returns Returns one of the T_STRING .. T_END enumeration codes.
uint8_t nextToken ();
/// Extract the last token as string (works for T_STRING and T_NUMBER).
/// @param plen This variable will receive the size, if present.
/// @return Returns pointer to a zero-terminated string in the decode buffer.
const char* asString (uint8_t* plen =0);
/// Extract the last token as number (also works for strings if numeric).
/// @return Returns the decoded integer, max 32-bit signed in this version.
long asNumber ();
protected:
void AddToBuf (char ch);
char level, *bufPtr;
uint8_t bufLen, count, next, last, state;
};
#endif