"Fossies" - the Fresh Open Source Software Archive 
Member "npadmin-0.14/berseq.C" (22 Nov 2002, 8460 Bytes) of package /linux/misc/old/npadmin-0.14.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /* Copyright (c) 2000 Ben Woodard
2 * All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public Licence
6 * as published by the Free Software Foundation; either version 2
7 * of the Licence, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRENTY; without even the implied warrenty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public Licence in the COPYING file for more
13 * details.
14 *
15 * You should have received a copy of the GNU Library General
16 * Public License along with the GNU C Library; see the file
17 * COPYING.LIB. If not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #include <string.h>
22 #include <assert.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #include "ber.h"
27
28 /* berSequence - sequences are wrappers for other encoded pieces of data.
29 * basically all that they do is give mark their beginning and have a length.
30 * the tricky bit is that they can be recursive. This is the real reason for
31 * mbufs.
32 * You sort of insert the other information into the sequence. The ber encoded
33 * information that you insert into a sequence is assumed to be owned by the
34 * sequence. It actually throws it away very shortly and just keeps the mbufs.
35 */
36
37 BerSequence::~BerSequence(){
38 for(BerBase *cur=head; cur!=NULL; ){
39 BerBase *tmp=cur;
40 cur=cur->next;
41 delete tmp;
42 }
43 }
44
45 BerSequence::BerSequence(unsigned char *str){
46 head=NULL;
47 tail=NULL;
48 assert(str[0]&CONSTRUCTOR_TAG);
49 unsigned char headlen;
50 tag=(Tags)str[0];
51 seqlen=unpack_len(str,headlen);
52
53 unsigned long myseqlen=0;
54 unsigned char junk; // used to store the headerlen and then dispose of it
55 for(unsigned char *curpos=str+headlen;curpos<str+headlen+seqlen;
56 curpos+=unpack_len(curpos,junk)+junk){
57 BerBase *newone;
58 // char tmpbuf[10240];
59 // int tmplen;
60 switch(*curpos){
61 case INT_TAG:
62 case COUNTER_TAG:
63 newone=new BerInt(curpos);
64 // tmplen=newone->print(tmpbuf,10239);
65 // tmpbuf[tmplen]=0;
66 // printf("%s\n\n",tmpbuf);
67 break;
68 case STRING_TAG:
69 newone=new BerString(curpos);
70 break;
71 case NULL_TAG:
72 newone=new BerNull(curpos);
73 break;
74 case OID_TAG:
75 newone=new BerOid(curpos);
76 break;
77 case TIME_TICK_TAG:
78 newone=new BerTimeTick(curpos);
79 break;
80 case IPADDR_TAG:
81 newone=new BerIPAddr(curpos);
82 break;
83 default:
84 newone=new BerSequence(curpos);
85 }
86 if(head==NULL)
87 tail=head=newone;
88 else {
89 tail->next=newone;
90 tail=tail->next;
91 }
92 myseqlen+=newone->fulllen();
93 }
94 unsigned char *tempstr=start_data((Tags)str[0],myseqlen,headlen);
95 edatacache=new BerEncodedData(tempstr,headlen);
96 // shorten the string because start_data creates a space big enough for the
97 // data as well.
98 edatacache->Data((unsigned char*)realloc(edatacache->Data(),headlen));
99 }
100
101 BerEncodedData *BerSequence::getdata(){
102 if(edatacache==NULL){
103 unsigned char headlen;
104 unsigned char *tmp=start_data(tag,seqlen,headlen);
105 tmp=(unsigned char*)realloc(tmp,headlen);
106 edatacache=new BerEncodedData(tmp,headlen);
107 }
108 if(edatacache->next==NULL){
109 BerEncodedData *loc_tail=edatacache;
110 for(BerBase *cur=head;cur!=NULL; cur=cur->next){
111 loc_tail->next=cur->getdata();
112 while(loc_tail->next)
113 loc_tail=loc_tail->next; // walk to the end of the list.
114 }
115 }
116 return edatacache;
117 }
118
119 BerEncodedData *BerSequence::encode(){
120 BerEncodedData *datlisthead=NULL,*curdat=NULL,*bedtail=NULL;
121
122 // string up the data
123 for(BerBase *cur=head; cur!=NULL; cur=cur->next){
124 // go to the end of the list.
125 curdat=cur->getdata();
126 if(datlisthead==NULL){
127 datlisthead=bedtail=curdat;
128 }else{
129 bedtail->next=curdat;
130 bedtail=bedtail->next;
131 }
132 while(bedtail->next)
133 bedtail=bedtail->next;
134 }
135
136 // encode the data
137 unsigned char headerlen=0;
138 unsigned char *retval=start_data(tag,seqlen,headerlen);
139 unsigned char *curpos=retval+headerlen;
140 for(curdat=datlisthead; curdat!=NULL;
141 curpos+=curdat->Length(), curdat=curdat->next){
142 memcpy(curpos, curdat->Data(), curdat->Length());
143 }
144 return new BerEncodedData(retval,seqlen+headerlen);
145 }
146
147 BerSequence::BerSequence(Tags newtag, unsigned int entries ...){
148 va_list berObs;
149 va_start(berObs,entries);
150 tag=newtag;
151
152 if(entries==0){
153 head=tail=NULL;
154 return;
155 }
156 BerBase *curBer=va_arg(berObs,BerBase*);
157 assert(curBer);
158 head=tail=curBer;
159 seqlen=curBer->fulllen();
160
161 //only count down to one because we have already taken one.
162 for(;entries>1;entries--){
163 curBer=va_arg(berObs,BerBase*);
164 assert(curBer);
165 seqlen+=curBer->fulllen();
166 tail->next=curBer;
167 tail=tail->next;
168 }
169
170 va_end(berObs);
171 }
172
173 // /* never tested */
174 // BerSequence::prepend(unsigned int num ...){
175 // va_list newones;
176 // va_start(newones,num);
177
178 // BerBase *newlist,*newtail;
179 // newtail=newlist=va_arg(newones,BerBase*);
180 // assert(newlist);
181 // seqlen+=newlist->fulllen();
182 // for(;num>1;num--){
183 // BerBase *curber=va_arg(newones,BerBase*);
184 // assert(curber);x
185 // seqlen+=curber->fulllen();
186 // newtail->next=curber;
187 // newtail=newtail->next;
188 // }
189 // newtail->next=head;
190 // head=newlist;
191
192 // va_end(newones);
193 // }
194
195
196 void BerSequence::append(unsigned int num ...){
197 va_list newones;
198 va_start(newones,num);
199
200 if(head==NULL){
201 head=tail=va_arg(newones,BerBase*);
202 seqlen=tail->fulllen();
203 num--;
204 }
205
206 while(num--){
207 tail->next=va_arg(newones,BerBase*);
208 assert(tail->next);
209 tail=tail->next;
210 seqlen+=tail->fulllen();
211 }
212
213 if(edatacache){
214 delete edatacache;
215 edatacache=NULL;
216 }
217 va_end(newones);
218 }
219
220 BerBase *BerSequence::peek(unsigned int num){
221 BerBase *cur;
222 for(cur=head;num && cur!=NULL;num--,cur=cur->next);
223 return cur;
224 }
225
226 BerBase *BerSequence::extract(unsigned int num){
227 BerBase *cur,*prev=NULL;
228 for(cur=head;num && cur!=NULL;num--,cur=cur->next)
229 prev=cur;
230 if(cur==NULL) return NULL;
231
232 // remove its length
233 /* The inital approach was to just subtract the fulllen but fullen walks
234 the list of the encoded data and so in effect it returns the remainder
235 of the sequence. Thus the sequence is too short. This subtracts the
236 correct amount and leaves the semantics of fulllen the same. However, I
237 am not sure that is the right thing to do. It might be worth it to change
238 the functioning of fulllen but I didn't want to take the time to figure
239 out all the other ways that might affect the code. */
240 unsigned char headlen;
241 seqlen-=unpack_len(cur->edatacache->Data(),headlen);
242 seqlen-=headlen;
243
244 /* got to fix up edatacache so that it matches current data */
245 unsigned char *newdat=start_data((Tags)(edatacache->Data())[0],seqlen,
246 headlen);
247 newdat=(unsigned char*)realloc(newdat,headlen);
248 assert(newdat);
249 BerEncodedData *oldedc=edatacache;
250 edatacache=new BerEncodedData(newdat,headlen);
251 edatacache->next=oldedc->next;
252 delete oldedc;
253
254 BerEncodedData *oldend;
255 if(cur==head){
256 head=head->next;
257 } else {
258 prev->next=cur->next;
259 /* find the entry that is cur's edatacache
260 and set it to the value of cur->next->edatacache
261 kind of sew the lists together */
262 if(cur->next!=NULL){
263 for(oldend=prev->edatacache;oldend->next!=cur->edatacache;
264 oldend=oldend->next){
265 assert(oldend->next!=NULL); /* I don't know what this would mean. If
266 it ever comes up. I guess I will have
267 to deal with it. */
268 }
269 oldend->next=cur->next->edatacache;
270 }
271 }
272 // make is so that cur->edatacache list doesn't merge into this list
273 if(cur->next){
274 for(oldend=cur->edatacache; oldend->next!=cur->next->edatacache;
275 oldend=oldend->next);
276 oldend->next=NULL;
277 }
278
279 if(cur==tail){
280 tail=prev;
281 }
282 cur->next=NULL;
283
284 return cur;
285 }
286
287 int BerSequence::print(char *buf, unsigned int len){
288 len-=2;
289 if(!len) return -1;
290 buf[0]='(';
291 buf[1]=' ';
292 buf+=2;
293 int totlen=1;
294 for( BerBase *cur=head; cur!=NULL; cur=cur->next){
295 int i=cur->print(buf,len);
296 if(i==-1) return -1;
297 len-=i+1;
298 buf+=i;
299 buf[0]=' ';
300 buf++;
301 totlen+=i+1;
302 }
303 if(!--len) return -1;
304 buf[0]=')';
305 buf[1]=' ';
306 return totlen+2;
307 }
308
309
310