"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