-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdata.cpp
140 lines (124 loc) · 3.36 KB
/
data.cpp
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
134
135
136
137
138
139
140
/**
* @file data.cpp
* @brief Brief description of file.
*
*/
#include "diamondapparatus.h"
#include "time.h"
#include <arpa/inet.h>
/*
* Message format for a datum:
* uint32_t msgtype
* uint32_t numitems
* byte namelen+1
* char name[namelen+1] (null term)
* for each item:
* byte type
* union {
* float f
* struct {
* uint32_t len
* char s[len];
* }
* }
*/
using namespace diamondapparatus;
Datum Topic::zeroDat;
const char *Topic::getNameFromMsg(const char *p){
p+=sizeof(uint32_t)*2+1;
return p;
}
const char *Topic::toMessage(int *size,int msgtype,const char *name){
int nll = strlen(name);
if(nll>128)nll=128;
uint8_t namelen = nll+1;
// first task - calculate the size.
*size = sizeof(uint32_t)*2; // msgtype and item count
*size += namelen+1; // namelen and name
std::vector<Datum>::iterator i;
for(i=d.begin();i!=d.end();++i){
(*size)++; // type byte
switch(i->t){
case DT_FLOAT:
*size+=sizeof(float);
break;
case DT_STRING:
*size+=sizeof(uint32_t); // length
*size+=strlen(i->d.s); // NOT nullterminated
break;
default:
throw DiamondException("bad data");
}
}
// now we have the size, alloc the buffer
char *buf = (char*)malloc(*size);
char *p = buf;
// and fill it in, remembering to perform conversions
*(uint32_t *)p = htonl(msgtype); p+=sizeof(uint32_t);
*(uint32_t *)p = htonl(d.size()); p+=sizeof(uint32_t);
*p++ = namelen;
strcpy(p,name); // this one is null terminated
p+=namelen;
for(i=d.begin();i!=d.end();++i){
int len;
*p++ = i->t; // type
switch(i->t){
case DT_FLOAT:
memcpy(p,&i->d.f,sizeof(float));
*(uint32_t *)p = htonl(*(uint32_t *)p);
p+=sizeof(float);
break;
case DT_STRING:
len = strlen(i->d.s);
*(uint32_t *)p = htonl(len);
p+= sizeof(uint32_t);
memcpy(p,i->d.s,len);
p+=len; // NOT nullterminated
break;
default:
throw DiamondException("bad data");
}
}
return buf;
}
uint32_t Topic::fromMessage(const char *p,char *namebuf){
d.clear();
uint32_t msg = ntohl(*(uint32_t *)p);p+=sizeof(uint32_t);
uint32_t count = ntohl(*(uint32_t *)p);p+=sizeof(uint32_t);
uint8_t namelen = *p++;
if(namebuf){
memcpy(namebuf,p,namelen);
namebuf[namelen]=0;
}
p+=namelen;
for(int i=0;i<count;i++){
int len;
Datum t; // temporary datum
switch(*p++){
case DT_FLOAT:
t.t = DT_FLOAT;
memcpy(&t.d.f,p,sizeof(float));
*(uint32_t *)(&t.d.f) = htonl(*(uint32_t *)(&t.d.f));
p+=sizeof(float);
break;
case DT_STRING:
t.t = DT_STRING;
len = ntohl(*(uint32_t *)p);
p+=sizeof(uint32_t);
t.d.s = (char *)malloc(len+1);
memcpy(t.d.s,p,len);
t.d.s[len]=0;
p+=len;
break;
default:
throw DiamondException("bad data in fromMessage");
}
d.push_back(t);
}
}
double Topic::age(){
if(timeLastSet<0)
return -1;
else
return Time::now() - timeLastSet;
}