Merge branch 'master' into jwi-bcc64xsingletonwarning
[ACE_TAO.git] / ACE / ASNMP / asnmp / oid.cpp
blobe6b1ed8f272dab12fc3d848d634ab52ef8687eef
2 //=============================================================================
3 /**
4 * @file oid.cpp
6 * This module contains the implementation of the oid class. This
7 * includes all protected and public member functions. The oid class
8 * may be compiled stand alone without the use of any other library.
10 * @author Peter E MellquistMichael R MacFaden mrm@cisco.com - rework & ACE port
12 //=============================================================================
14 /*===================================================================
15 Copyright (c) 1996
16 Hewlett-Packard Company
18 ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
19 Permission to use, copy, modify, distribute and/or sell this software
20 and/or its documentation is hereby granted without fee. User agrees
21 to display the above copyright notice and this license notice in all
22 copies of the software and any documentation of the software. User
23 agrees to assume all liability for the use of the software; Hewlett-Packard
24 makes no representations about the suitability of this software for any
25 purpose. It is provided "AS-IS" without warranty of any kind,either express
26 or implied. User hereby grants a royalty-free license to any and all
27 derivatives based upon this software code base.
28 =====================================================================*/
30 //---------[ external C libraries used ]--------------------------------
32 #include "asnmp/oid.h" // include def for oid class
33 #include "ace/OS_NS_string.h"
34 #include "ace/OS_NS_stdio.h"
35 #include "ace/OS_Memory.h"
36 #include "ace/OS_NS_ctype.h"
38 enum Defs {SNMPBUFFSIZE=300,
39 SNMPCHARSIZE=15}; // max oid value (4294967295UL)
41 #define NO_MEM_STR "ERROR: Oid::to_string: memory allocation failure"
43 //=============[Oid::get_syntax()]====================================
44 SmiUINT32 Oid::get_syntax()
46 return sNMP_SYNTAX_OID;
50 //=============[Oid::Oid( const char *dotted_string ]=====================
51 // constructor using a dotted string
53 // do a string to oid using the string passed in
54 Oid::Oid( const char * dotted_oid_string, size_t size)
56 // can't init enum SmiValue so just memset it clean
57 set_null();
59 size_t z;
60 if ((z = ACE_OS::strlen(dotted_oid_string)) == 0) {
61 set_invalid();
62 return;
65 if (size == (unsigned int)-1)
66 size = z;
67 if (size > z)
68 size = z;
70 char *ptr = (char *)dotted_oid_string;;
71 if (size < z) {
72 // create new buffer if needed
73 ACE_NEW(ptr, char [size]);
75 // sz should be in StrToOid?
76 ACE_OS::memcpy( (void *)ptr, dotted_oid_string, size);
79 size_t byte_counter;
80 if (StrToOid( (char *) ptr, &smival.value.oid, byte_counter) < 0)
81 set_invalid();
82 if (ptr != dotted_oid_string)
83 delete [] ptr;
87 //=============[Oid::Oid( const Oid &oid) ]================================
88 // constructor using another oid object
90 // do an oid copy using the oid object passed in
91 Oid::Oid ( const Oid &oid)
92 : SnmpSyntax (oid)
94 set_null();
96 // allocate some memory for the oid
97 // in this case the size to allocate is the same
98 // size as the source oid
99 if (oid.smival.value.oid.len) {
100 ACE_NEW(smival.value.oid.ptr, SmiUINT32[ oid.smival.value.oid.len]);
101 size_t byte_counter;
102 OidCopy( (SmiLPOID) &(oid.smival.value.oid),(SmiLPOID)
103 &smival.value.oid, byte_counter);
108 //=============[Oid::Oid( const unsigned long *raw_oid, int oid_len) ]====
109 // constructor using raw numeric form
111 // copy the integer values into the private member
112 Oid::Oid(const unsigned long *raw_oid, size_t oid_len)
114 set_null();
116 smival.syntax = sNMP_SYNTAX_OID;
117 set_invalid();
119 if (raw_oid && oid_len > 0) {
120 ACE_NEW(smival.value.oid.ptr, SmiUINT32[ oid_len]);
121 smival.value.oid.len = oid_len;
122 for (size_t i=0; i < oid_len; i++)
123 smival.value.oid.ptr[i] = raw_oid[i];
127 //=============[Oid::~Oid]==============================================
128 // destructor
130 // free up the descriptor space
131 Oid::~Oid()
133 // free up the octet deep memory
134 if ( smival.value.oid.ptr ) {
135 set_invalid();
138 // free up the output string
139 if ( iv_str != 0)
140 delete [] iv_str;
144 //=============[Oid::operator = const char * dotted_string ]==============
145 // assignment to a string operator overloaded
147 // free the existing oid
148 // create the new oid from the string
149 // return this object
150 void Oid::set_data( const char *dotted_oid_string)
152 // delete the old value
153 if ( smival.value.oid.ptr ) {
154 set_invalid();
157 // assign the new value
158 size_t byte_counter;
159 if (StrToOid( (char *) dotted_oid_string, &smival.value.oid, byte_counter) <0)
160 set_invalid();
164 //=============[Oid:: operator = const Oid &oid ]==========================
165 // assignment to another oid object overloaded
167 // free the existing oid
168 // create a new one from the object passed in
169 // TODO: measure perf vs memory of no realloc in case where len >= oid.len
170 Oid& Oid::operator=( const Oid &oid)
172 // protect against assignment from self
173 if ( this == &oid)
174 return *this;
176 set_invalid();
178 // check for zero len on source
179 if ( oid.smival.value.oid.len == 0)
180 return *this;
182 const SmiLPOID srcOid = (SmiLPOID) &(oid.smival.value.oid);
183 init_value(srcOid, oid.smival.value.oid.len);
184 return *this;
187 // assign this object the oid, set to invalid if copy fails
188 void Oid::init_value(const SmiLPOID srcOid, size_t len)
190 // allocate some memory for the oid
191 ACE_NEW(smival.value.oid.ptr, SmiUINT32[ len]);
192 size_t byte_counter;
193 OidCopy( srcOid, (SmiLPOID) &smival.value.oid, byte_counter);
196 void Oid::init_value(const unsigned long *raw_oid, size_t oid_len)
198 if (smival.value.oid.ptr)
199 delete [] smival.value.oid.ptr;
201 ACE_NEW(smival.value.oid.ptr, SmiUINT32[ oid_len]);
202 ACE_OS::memcpy((SmiLPBYTE) smival.value.oid.ptr,
203 (SmiLPBYTE) raw_oid,
204 (size_t) (oid_len * sizeof(SmiUINT32)));
205 smival.value.oid.len = oid_len;
208 //==============[Oid:: operator += const char *a ]=========================
209 // append operator, appends a string
211 // allocate some space for a max oid string
212 // extract current string into space
213 // concat new string
214 // free up existing oid
215 // make a new oid from string
216 // delete allocated space
217 Oid& Oid::operator+=( const char *a)
219 unsigned long n;
221 if (!a)
222 return *this;
224 if ( *a=='.')
225 a++;
226 size_t sz = ACE_OS::strlen(a);
228 if (valid()) {
229 n = (smival.value.oid.len *SNMPCHARSIZE) + smival.value.oid.len + 1 + sz;
230 char *ptr;
231 ACE_NEW_RETURN(ptr, char[ n], *this);
232 size_t byte_counter;
233 if (OidToStr(&smival.value.oid, n,ptr, byte_counter) > 0) {
234 delete [] ptr;
235 set_invalid();
236 return *this;
239 if (ACE_OS::strlen(ptr))
240 ACE_OS::strcat(ptr,".");
241 ACE_OS::strcat(ptr,a);
242 if ( smival.value.oid.len !=0) {
243 set_invalid();
246 if (StrToOid( (char *) ptr, &smival.value.oid, byte_counter) < 0) {
247 set_invalid();
249 delete [] ptr;
251 else {
252 size_t byte_counter;
253 if (StrToOid( (char *) a, &smival.value.oid, byte_counter) < 0) {
254 set_invalid();
258 return *this;
261 //=============[ bool operator == oid,oid ]=================================
262 // equivlence operator overloaded
263 bool operator==( const Oid &lhs, const Oid &rhs)
265 // ensure same len, then use left_comparison
266 if (rhs.length() != lhs.length())
267 return false;
268 if( lhs.left_comparison( rhs.length(), rhs) == 0)
269 return true;
270 else
271 return false;
274 //==============[ bool operator!=( Oid &x,Oid &y) ]=======================
275 //not equivlence operator overloaded
276 bool operator!=( const Oid &lhs,const Oid &rhs)
278 return (!(lhs == rhs));
281 //==============[ bool operator<( Oid &x,Oid &y) ]========================
282 // less than < overloaded
283 bool operator<( const Oid &lhs,const Oid &rhs)
285 int result;
287 // call left_comparison with the current
288 // Oidx, Oidy and len of Oidx
289 if ((result = lhs.left_comparison( rhs.length(), rhs)) < 0)
290 return true;
291 else if (result > 0)
292 return false;
294 else{
295 // if here, equivalent substrings, call the shorter one <
296 if (lhs.length() < rhs.length())
297 return true;
298 else
299 return false;
303 //==============[ bool operator<=( Oid &x,Oid &y) ]=======================
304 // less than <= overloaded
305 bool operator<=( const Oid &x,const Oid &y)
307 if ( (x < y) || (x == y) )
308 return true;
309 else
310 return false;
313 //==============[ bool operator>( Oid &x,Oid &y) ]========================
314 // greater than > overloaded
315 bool operator>( const Oid &x,const Oid &y)
317 // just invert existing <=
318 if (!(x<=y))
319 return true;
320 else
321 return false;
324 //==============[ bool operator>=( Oid &x,Oid &y) ]=======================
325 // greater than >= overloaded
326 bool operator>=( const Oid &x,const Oid &y)
328 // just invert existing <
329 if (!(x<y))
330 return true;
331 else
332 return false;
335 //===============[Oid::oidval ]=============================================
336 // return the WinSnmp oid part
337 SmiLPOID Oid::oidval()
339 return (SmiLPOID) &smival.value.oid;
342 //===============[Oid::set_data ]==---=====================================
343 // copy data from raw form...
344 void Oid::set_data( const unsigned long *raw_oid, const size_t oid_len)
346 if (smival.value.oid.len < oid_len) {
347 if ( smival.value.oid.ptr) {
348 set_invalid();
351 init_value(raw_oid, oid_len);
355 //===============[Oid::len ]================================================
356 // return the len of the oid
357 size_t Oid::length() const
359 return smival.value.oid.len;
362 //===============[Oid::trim( unsigned int) ]============================
363 // trim off the n leftmost values of an oid
364 // Note!, does not adjust actual space for
365 // speed
366 void Oid::trim( const size_t n)
368 // verify that n is legal
369 if ((n<=smival.value.oid.len)&&(n>0)) {
370 smival.value.oid.len -= n;
372 if (smival.value.oid.len == 0) {
373 set_invalid();
378 //===============[Oid::set_invalid() ]====================
379 // make this object invalid by resetting all values
380 void Oid::set_invalid() {
381 delete [] smival.value.oid.ptr;
382 smival.value.oid.ptr = 0;
383 smival.value.oid.len = 0;
384 delete [] iv_str;
385 iv_str = 0;
388 //===============[Oid::set_null() ]====================
389 void Oid::set_null() {
390 smival.syntax = sNMP_SYNTAX_OID;
391 smival.value.oid.ptr = 0;
392 smival.value.oid.len = 0;
393 iv_str = 0;
396 //===============[Oid::operator += const unsigned int) ]====================
397 // append operator, appends an int
399 // allocate some space for a max oid string
400 // extract current string into space
401 // concat new string
402 // free up existing oid
403 // make a new oid from string
404 // delete allocated space
405 Oid& Oid::operator+=( const unsigned long i)
407 unsigned long n = (smival.value.oid.len * SNMPCHARSIZE)
408 + ( smival.value.oid.len -1) + 1 + 4;
409 char buffer[SNMPBUFFSIZE];
411 // two cases: null oid, existing oid
412 if (valid()) {
413 // allocate some temporary space
414 char *ptr;
415 ACE_NEW_RETURN(ptr, char[ n], *this);
416 size_t byte_counter;
417 if (OidToStr(&smival.value.oid, n, ptr, byte_counter) < 0) {
418 set_invalid();
419 delete [] ptr;
420 return *this;
423 if (ACE_OS::strlen(ptr))
424 ACE_OS::strcat(ptr,".");
426 if (ACE_OS::sprintf( buffer,"%lu",i) != -1) {
427 ACE_OS::strcat(ptr, buffer);
428 if ( smival.value.oid.ptr ) {
429 set_invalid();
431 if (StrToOid( (char *) ptr, &smival.value.oid, byte_counter) < 0) {
432 set_invalid();
434 delete [] ptr;
437 else {
438 init_value((const unsigned long *)&i, (size_t)1);
441 return *this;
444 //===============[Oid::operator += const Oid) ]========================
445 // append operator, appends an Oid
447 // allocate some space for a max oid string
448 // extract current string into space
449 // concat new string
450 // free up existing oid
451 // make a new oid from string
452 // delete allocated space
453 Oid& Oid::operator+=( const Oid &o)
455 SmiLPUINT32 new_oid;
457 if (o.smival.value.oid.len == 0)
458 return *this;
460 ACE_NEW_RETURN(new_oid,
461 SmiUINT32[ smival.value.oid.len + o.smival.value.oid.len], *this);
462 if (smival.value.oid.ptr) {
463 ACE_OS::memcpy((SmiLPBYTE) new_oid,
464 (SmiLPBYTE) smival.value.oid.ptr,
465 (size_t) (smival.value.oid.len*sizeof(SmiUINT32)));
467 delete [] smival.value.oid.ptr;
470 // out with the old, in with the new...
471 smival.value.oid.ptr = new_oid;
473 ACE_OS::memcpy((SmiLPBYTE) &new_oid[smival.value.oid.len],
474 (SmiLPBYTE) o.smival.value.oid.ptr,
475 (size_t) (o.smival.value.oid.len*sizeof(SmiUINT32)));
477 smival.value.oid.len += o.smival.value.oid.len;
478 return *this;
481 // return string portion of the oid
483 const char * Oid::to_string()
485 unsigned long n;
486 if (!valid())
487 return ""; // be consistent with other classes
489 // the worst case char len of an oid can be..
490 // oid.len*3 + dots in between if each oid is XXXX
491 // so.. size = (len*4) + (len-1) + 1 , extra for a null
493 n = (smival.value.oid.len *SNMPCHARSIZE) + ( smival.value.oid.len -1) + 1 ;
494 if (n == 0)
495 n = 1; // need at least 1 byte for a null string
497 // adjust the len of output array in case size was adjusted
498 if ( iv_str != 0)
499 delete [] iv_str;
500 // allocate some space for the output string
501 ACE_NEW_RETURN(iv_str, char[ n], "");
503 // convert to an output string
504 size_t how_many;
505 if ( valid() && iv_str != 0)
506 if (OidToStr(&smival.value.oid,n,iv_str, how_many) < 0)
507 return "ERROR: Oid::OidToStr failed";
508 return iv_str;
511 //==============[Oid::suboid( unsigned int start, n) ]=============
512 int Oid::suboid(Oid& new_oid, size_t start, size_t how_many)
514 if (how_many == 0)
515 return 0;
516 else
517 if (how_many == (size_t)-1)
518 how_many = length();
519 else
520 if (how_many > length())
521 how_many = length();
523 // reset new_oid
524 new_oid.set_invalid();
526 size_t new_size = how_many - start;
527 if (new_size == 0)
528 new_size++;
529 new_oid.smival.value.oid.len = new_size;
530 ACE_NEW_RETURN(new_oid.smival.value.oid.ptr,
531 SmiUINT32 [ new_oid.smival.value.oid.len], -1);
532 // copy source to destination
533 ACE_OS::memcpy( (SmiLPBYTE) new_oid.smival.value.oid.ptr,
534 (SmiLPBYTE) (smival.value.oid.ptr + start),
535 new_size * sizeof(SmiLPBYTE));
536 return 0;
540 //=============[Oid::StrToOid( char *string, SmiLPOID dst) ]==============
541 // convert a string to an oid
542 int Oid::StrToOid( const char *string, SmiLPOID dstOid, size_t& how_many)
544 size_t index = 0;
545 size_t number = 0;
547 // make a temp buffer to copy the data into first
548 SmiLPUINT32 temp;
549 unsigned long nz;
551 if (string && *string) {
552 nz = ACE_OS::strlen( string);
554 else {
555 dstOid->len = 0;
556 dstOid->ptr = 0;
557 return -1;
560 ACE_NEW_RETURN(temp, SmiUINT32[ nz], -1);
561 while (*string!=0 && index<nz) {
562 // init the number for each token
563 number = 0;
564 // skip over the dot
565 if (*string=='.')
566 string++;
568 // grab a digit token and convert it to a long int
569 while (ACE_OS::ace_isdigit(*string))
570 number=number*10 + *(string++)-'0';
572 // check for invalid chars
573 if (*string!=0 && *string!='.') {
574 // Error: Invalid character in string
575 delete [] temp;
576 return -1;
579 // stuff the value into the array
580 temp[index] = number;
581 index++; // bump the counter
585 // get some space for the real oid
586 ACE_NEW_RETURN(dstOid->ptr, SmiUINT32[ index], -1);
587 // TODO: make tmp autoptr type delete [] temp to prevent leak
589 // copy in the temp data
590 ACE_OS::memcpy((SmiLPBYTE) dstOid->ptr, (SmiLPBYTE) temp,
591 (size_t) (index*sizeof(SmiUINT32)));
593 // set the len of the oid
594 dstOid->len = index;
596 // free up temp data
597 delete [] temp;
599 how_many = index;
600 return 0;
604 //===============[Oid::OidCopy( source, destination) ]====================
605 // Copy an oid, return bytes copied
606 int Oid::OidCopy( SmiLPOID srcOid, SmiLPOID dstOid, size_t& how_many_bytes)
608 // check source len ! zero
609 if (srcOid->len == 0)
610 return -1;
612 // copy source to destination
613 ACE_OS::memcpy((SmiLPBYTE) dstOid->ptr,
614 (SmiLPBYTE) srcOid->ptr,
615 (size_t) (srcOid->len * sizeof(SmiUINT32)));
617 //set the new len
618 dstOid->len = srcOid->len;
619 how_many_bytes = srcOid->len;
621 return 0;
625 //===============[Oid::left_comparison( n, Oid) ]=================================
626 // compare the n leftmost values of two oids ( left-to_right )
628 // self == Oid then return 0, they are equal
629 // self < Oid then return -1, <
630 // self > Oid then return 1, >
631 int Oid::left_comparison( const unsigned long n, const Oid &o) const
633 unsigned long z;
634 unsigned long len = n;
635 int reduced_len = 0;
637 // 1st case they both are null
638 if (( len==0)&&( this->smival.value.oid.len==0))
639 return 0; // equal
641 // verify that n is valid, must be >= 0
642 if ( len <=0)
643 return 1; // ! equal
645 // only compare for the minimal length
646 if (len > this->smival.value.oid.len) {
647 len = this->smival.value.oid.len;
648 reduced_len = 1;
650 if (len > o.smival.value.oid.len) {
651 len = o.smival.value.oid.len;
652 reduced_len = 1;
655 z = 0;
656 while(z < len) {
657 if ( this->smival.value.oid.ptr[z] < o.smival.value.oid.ptr[z])
658 return -1; // less than
659 if ( this->smival.value.oid.ptr[z] > o.smival.value.oid.ptr[z])
660 return 1; // greater than
661 z++;
664 // if we truncated the len then these may not be equal
665 if (reduced_len) {
666 if (this->smival.value.oid.len < o.smival.value.oid.len)
667 return -1;
668 if (this->smival.value.oid.len > o.smival.value.oid.len)
669 return 1;
671 return 0; // equal
676 //===============[Oid::left_comparison( n, Oid) ]=================================
677 // compare the n rightmost bytes (right-to-left)
678 // returns 0, equal
679 // returns -1, <
680 // returns 1 , >
681 int Oid::right_comparison( const unsigned long n, const Oid &o) const
683 // oid to compare must have at least the same number
684 // of sub-ids to comparison else the argument Oid is
685 // less than THIS
686 if ( o.length() < n)
687 return -1;
689 // also can't compare argument oid for sub-ids which
690 // THIS does not have
691 if ( this->length() < n)
692 return -1;
694 int start = (int) this->length();
695 int end = (int) start - (int) n;
696 for ( int z=start;z< end;z--)
698 if ( o.smival.value.oid.ptr[z] < this->smival.value.oid.ptr[z])
699 return -1;
700 if ( o.smival.value.oid.ptr[z] > this->smival.value.oid.ptr[z])
701 return 1;
704 return 0; // they are equal
709 //================[ Oid::valid() ]========================================
710 // is the Oid object valid
711 // returns validity
712 int Oid::valid() const
714 return ( smival.value.oid.ptr ? 1 : 0 );
717 //================[Oid::OidToStr ]=========================================
718 // convert an oid to a string
719 int Oid::OidToStr( SmiLPOID srcOid, unsigned long size,
720 char *string, size_t& how_many_bytes)
722 unsigned long index = 0;
723 unsigned totLen = 0;
724 char szNumber[SNMPBUFFSIZE];
726 // init the string
727 string[totLen] = 0;
729 // verify there is something to copy
730 if (srcOid->len == 0)
731 return -1;
733 // loop through and build up a string
734 for (index=0; index < srcOid->len; index++) {
735 // convert data element to a string
736 if (ACE_OS::sprintf( szNumber,"%lu", srcOid->ptr[index]) == -1)
737 return -1;
739 // verify len is not over
740 if (totLen + ACE_OS::strlen(szNumber) + 1 >= size)
741 return -2;
743 // if not at end, pad with a dot
744 if (totLen!=0)
745 string[totLen++] = '.';
747 // copy the string token into the main string
748 ACE_OS::strcpy(string + totLen, szNumber);
750 // adjust the total len
751 totLen += ACE_OS::strlen(szNumber);
754 how_many_bytes = totLen + 1;
755 return 0;
759 //================[ general Value = operator ]========================
760 SnmpSyntax& Oid::operator=( SnmpSyntax &val)
762 // protect against assignment from self
763 if ( this == &val )
764 return *this;
766 // blow away old value
767 smival.value.oid.len = 0;
768 if (smival.value.oid.ptr) {
769 set_invalid();
772 // assign new value
773 if (val.valid()) {
774 switch (val.get_syntax()) {
775 case sNMP_SYNTAX_OID:
776 set_data( ((Oid &)val).smival.value.oid.ptr,
777 (unsigned int)((Oid &)val).smival.value.oid.len);
778 break;
781 return *this;
784 //================[ [] operator ]=====================================
785 unsigned long& Oid::operator[](size_t position)
787 return smival.value.oid.ptr[position];
790 //================[ clone ]===========================================
791 SnmpSyntax *Oid::clone() const
793 return (SnmpSyntax *) new Oid(*this);