1 /*_############################################################################
6 _## -----------------------------------------------
7 _## Copyright (c) 2001-2010 Jochen Katz, Frank Fock
9 _## This software is based on SNMP++2.6 from Hewlett Packard:
11 _## Copyright (c) 1996
12 _## Hewlett-Packard Company
14 _## ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
15 _## Permission to use, copy, modify, distribute and/or sell this software
16 _## and/or its documentation is hereby granted without fee. User agrees
17 _## to display the above copyright notice and this license notice in all
18 _## copies of the software and any documentation of the software. User
19 _## agrees to assume all liability for the use of the software;
20 _## Hewlett-Packard and Jochen Katz make no representations about the
21 _## suitability of this software for any purpose. It is provided
22 _## "AS-IS" without warranty of any kind, either express or implied. User
23 _## hereby grants a royalty-free license to any and all derivatives based
24 _## upon this software code base.
26 _## Stuttgart, Germany, Thu Sep 2 00:07:47 CEST 2010
28 _##########################################################################*/
29 /*===================================================================
32 Hewlett-Packard Company
34 ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
35 Permission to use, copy, modify, distribute and/or sell this software
36 and/or its documentation is hereby granted without fee. User agrees
37 to display the above copyright notice and this license notice in all
38 copies of the software and any documentation of the software. User
39 agrees to assume all liability for the use of the software; Hewlett-Packard
40 makes no representations about the suitability of this software for any
41 purpose. It is provided "AS-IS" without warranty of any kind,either express
42 or implied. User hereby grants a royalty-free license to any and all
43 derivatives based upon this software code base.
47 OID CLASS IMPLEMENTATION
49 DESIGN + AUTHOR: Peter E. Mellquist
52 This module contains the implementation of the oid class. This
53 includes all protected and public member functions. The oid class
54 may be compiled stand alone without the use of any other library.
55 =====================================================================*/
56 char oid_cpp_version[]="#(@) SNMP++ $Id: oid.cpp 1742 2010-04-29 19:08:54Z katz $";
58 //---------[ external C libaries used ]--------------------------------
59 #include <stdio.h> // standard io
60 #if !(defined (CPU) && CPU == PPC603)
61 #include <memory.h> // memcpy's
63 #include <string.h> // strlen, etc..
64 #include <stdlib.h> // standard library
65 #include <ctype.h> // isdigit
66 #include <stdlib.h> // malloc, free
68 #include "snmp_pp/oid.h" // include def for oid class
70 #ifdef SNMP_PP_NAMESPACE
74 #define SNMPBUFFSIZE 11 // size of scratch buffer
75 #define SNMPCHARSIZE 11 // an individual oid instance as a string
77 /* Borlands isdigit has a bug */
79 #define my_isdigit(c) ((c) >= '0' && (c) <= '9')
81 #define my_isdigit isdigit
84 //=============[Oid::Oid(void)]============================================
85 // constructor using no arguments
86 // initialize octet ptr and string
88 Oid::Oid() : iv_str(0), iv_part_str(0), m_changed(true)
90 smival.syntax = sNMP_SYNTAX_OID;
91 smival.value.oid.len = 0;
92 smival.value.oid.ptr = 0;
96 //=============[Oid::Oid(const char *dotted_string ]=====================
97 // constructor using a dotted string
99 // do a string to oid using the string passed in
100 Oid::Oid(const char *oid_string, const bool is_dotted_oid_string)
101 : iv_str(0), iv_part_str(0), m_changed(true)
103 smival.syntax = sNMP_SYNTAX_OID;
104 smival.value.oid.len = 0;
105 smival.value.oid.ptr = 0;
107 if (is_dotted_oid_string)
108 StrToOid(oid_string, &smival.value.oid);
110 set_data(oid_string, oid_string ? strlen(oid_string) : 0);
114 //=============[Oid::Oid(const Oid &oid) ]================================
115 // constructor using another oid object
117 // do an oid copy using the oid object passed in
118 Oid::Oid(const Oid &oid)
119 : iv_str(0), iv_part_str(0), m_changed(true)
121 smival.syntax = sNMP_SYNTAX_OID;
122 smival.value.oid.len = 0;
123 smival.value.oid.ptr = 0;
125 // allocate some memory for the oid
126 // in this case the size to allocate is the same size as the source oid
127 if (oid.smival.value.oid.len)
129 smival.value.oid.ptr = (SmiLPUINT32) new unsigned long[oid.smival.value.oid.len];
130 if (smival.value.oid.ptr)
131 OidCopy((SmiLPOID)&(oid.smival.value.oid), (SmiLPOID)&smival.value.oid);
136 //=============[Oid::Oid(const unsigned long *raw_oid, int oid_len) ]====
137 // constructor using raw numeric form
139 // copy the integer values into the private member
140 Oid::Oid(const unsigned long *raw_oid, int oid_len)
141 : iv_str(0), iv_part_str(0), m_changed(true)
143 smival.syntax = sNMP_SYNTAX_OID;
144 smival.value.oid.len = 0;
145 smival.value.oid.ptr = 0;
147 if (raw_oid && (oid_len > 0))
149 smival.value.oid.ptr = (SmiLPUINT32) new unsigned long[oid_len];
150 if (smival.value.oid.ptr)
152 smival.value.oid.len = oid_len;
153 for (int i=0; i < oid_len; i++)
154 smival.value.oid.ptr[i] = raw_oid[i];
159 //=============[Oid::~Oid]==============================================
163 if (iv_str) delete [] iv_str; // free up the output string
164 if (iv_part_str) delete [] iv_part_str; // free up the output string
168 //=============[Oid::operator = const char * dotted_string ]==============
169 // assignment to a string operator overloaded
171 // free the existing oid
172 // create the new oid from the string
173 // return this object
174 Oid& Oid::operator=(const char *dotted_oid_string)
178 // assign the new value
179 StrToOid(dotted_oid_string, &smival.value.oid);
184 //=============[Oid:: operator = const Oid &oid ]==========================
185 // assignment to another oid object overloaded
187 // free the existing oid
188 // create a new one from the object passed in
189 Oid& Oid::operator=(const Oid &oid)
191 if (this == &oid) return *this; // protect against assignment from self
195 // check for zero len on source
196 if (oid.smival.value.oid.len == 0)
199 // allocate some memory for the oid
200 smival.value.oid.ptr = (SmiLPUINT32) new unsigned long[oid.smival.value.oid.len];
201 if (smival.value.oid.ptr)
202 OidCopy((SmiLPOID)&(oid.smival.value.oid), (SmiLPOID)&smival.value.oid);
207 //==============[Oid:: operator += const char *a ]=========================
208 // append operator, appends a string
210 // allocate some space for a max oid string
211 // extract current string into space
213 // free up existing oid
214 // make a new oid from string
215 // delete allocated space
216 Oid& Oid::operator+=(const char *a)
220 if (!a) return *this;
224 n = (smival.value.oid.len * SNMPCHARSIZE) + (smival.value.oid.len)
225 + 1 + SAFE_UINT_CAST(strlen(a));
226 char *ptr = new char[n];
229 /// @todo optimze this function (avoid conversion to string)
230 OidToStr(&smival.value.oid, n, ptr);
237 StrToOid(ptr, &smival.value.oid);
243 //=============[ int operator == oid,oid ]=================================
244 // equivlence operator overloaded
245 int operator==(const Oid &lhs, const Oid &rhs)
247 // ensure same len, then use nCompare
248 if (rhs.len() != lhs.len()) return 0;
249 return (lhs.nCompare(rhs.len(), rhs) == 0);
252 //==============[ operator<(Oid &x,Oid &y) ]=============================
253 // less than < overloaded
254 int operator<(const Oid &lhs, const Oid &rhs)
257 // call nCompare with the current
258 // Oidx, Oidy and len of Oidx
259 if((result = lhs.nCompare(rhs.len(), rhs))<0) return 1;
260 if (result > 0) return 0;
262 // if here, equivalent substrings, call the shorter one <
263 return (lhs.len() < rhs.len());
266 //==============[ operator==(Oid &x,char *) ]=============================
267 // equivlence operator overloaded
268 int operator==(const Oid &x, const char *dotted_oid_string)
270 Oid to(dotted_oid_string); // create a temp oid object
271 return (x == to); // compare using existing operator
274 //==============[ operator!=(Oid &x,char*) ]=============================
275 // not equivlence operator overloaded
276 int operator!=(const Oid &x, const char *dotted_oid_string)
278 Oid to(dotted_oid_string); // create a temp oid object
279 return (x != to); // compare using existing operator
282 //==============[ operator<(Oid &x,char*) ]=============================
283 // less than < operator overloaded
284 int operator<(const Oid &x, const char *dotted_oid_string)
286 Oid to(dotted_oid_string); // create a temp oid object
287 return (x < to); // compare using existing operator
290 //==============[ operator<=(Oid &x,char *) ]=============================
291 // less than <= operator overloaded
292 int operator<=(const Oid &x,char *dotted_oid_string)
294 Oid to(dotted_oid_string); // create a temp oid object
295 return (x <= to); // compare using existing operator
298 //==============[ operator>(Oid &x,char* ]=============================
299 // greater than > operator overloaded
300 int operator>(const Oid &x,const char *dotted_oid_string)
302 Oid to(dotted_oid_string); // create a temp oid object
303 return (x > to); // compare using existing operator
306 //==============[ operator>=(Oid &x,char*) ]=============================
307 // greater than >= operator overloaded
308 int operator>=(const Oid &x,const char *dotted_oid_string)
310 Oid to(dotted_oid_string); // create a temp oid object
311 return (x >= to); // compare using existing operator
314 //===============[Oid::set_data ]==---=====================================
315 // copy data from raw form...
316 void Oid::set_data(const unsigned long *raw_oid,
317 const unsigned int oid_len)
319 if (smival.value.oid.len < oid_len)
323 smival.value.oid.ptr = (SmiLPUINT32) new unsigned long[oid_len];
324 if (!smival.value.oid.ptr) return;
326 MEMCPY((SmiLPBYTE) smival.value.oid.ptr,
328 (size_t) (oid_len*sizeof(SmiUINT32)));
329 smival.value.oid.len = oid_len;
333 // Set the data from raw form.
334 void Oid::set_data(const char *str, const unsigned int str_len)
336 if (smival.value.oid.len < str_len)
340 smival.value.oid.ptr = (SmiLPUINT32) new unsigned long[str_len];
341 if (!smival.value.oid.ptr) return;
344 if ((!str) || (str_len == 0))
347 for (unsigned int i=0; i<str_len; i++)
348 smival.value.oid.ptr[i] = str[i];
350 smival.value.oid.len = str_len;
354 //===============[Oid::trim(unsigned int) ]============================
355 // trim off the n leftmost values of an oid
356 // Note!, does not adjust actual space for
358 void Oid::trim(const unsigned long n)
360 // verify that n is legal
361 if ((n <= smival.value.oid.len) && (n > 0))
363 smival.value.oid.len -= n;
364 if (smival.value.oid.len == 0)
370 //===============[Oid::operator += const unsigned int) ]====================
371 // append operator, appends an int
373 Oid& Oid::operator+=(const unsigned long i)
380 //===============[Oid::operator += const Oid) ]========================
381 // append operator, appends an Oid
383 // allocate some space for a max oid string
384 // extract current string into space
386 // free up existing oid
387 // make a new oid from string
388 // delete allocated space
389 Oid& Oid::operator+=(const Oid &o)
393 if (o.smival.value.oid.len == 0)
396 new_oid = (SmiLPUINT32) new unsigned long[smival.value.oid.len + o.smival.value.oid.len];
403 if (smival.value.oid.ptr)
405 MEMCPY((SmiLPBYTE) new_oid,
406 (SmiLPBYTE) smival.value.oid.ptr,
407 (size_t) (smival.value.oid.len*sizeof(SmiUINT32)));
409 delete [] smival.value.oid.ptr;
412 // out with the old, in with the new...
413 smival.value.oid.ptr = new_oid;
415 MEMCPY((SmiLPBYTE) &new_oid[smival.value.oid.len],
416 (SmiLPBYTE) o.smival.value.oid.ptr,
417 (size_t) (o.smival.value.oid.len*sizeof(SmiUINT32)));
419 smival.value.oid.len += o.smival.value.oid.len;
425 //==============[Oid::get_printable(unsigned int start, n) ]=============
426 // return a dotted string starting at start,
427 // going n positions to the left
428 // NOTE, start is 1 based (the first id is at position #1)
429 const char *Oid::get_printable(const unsigned long start,
430 const unsigned long n,
433 if (!m_changed && (buffer == iv_str)) return buffer;
436 unsigned long my_start = start - 1;
437 unsigned long my_end = my_start + n;
439 nz = (smival.value.oid.len * (SNMPCHARSIZE + 1)) + 1;
441 if (buffer) delete [] buffer; // delete the previous output string
443 buffer = new char[nz]; // allocate some space for the output string
447 buffer[0] = 0; // init the string
449 // cannot ask for more than there is..
450 if ((start == 0) || (my_end > smival.value.oid.len))
453 char *cur_ptr = buffer;
456 // loop through and build up a string
457 for (unsigned long index = my_start; index < my_end; ++index)
459 // if not at begin, pad with a dot
465 // convert data element to a string
466 cur_ptr += sprintf(cur_ptr, "%lu", smival.value.oid.ptr[index]);
469 if (buffer == iv_str)
471 Oid *nc_this = PP_CONST_CAST(Oid*, this);
472 nc_this->m_changed = false;
479 //=============[Oid::StrToOid(char *string, SmiLPOID dst) ]==============
480 // convert a string to an oid
481 int Oid::StrToOid(const char *str, SmiLPOID dstOid) const
483 unsigned int index = 0;
485 // make a temp buffer to copy the data into first
491 nz = SAFE_UINT_CAST(strlen(str));
499 temp = (SmiLPUINT32) new unsigned long[nz];
501 if (temp == 0) return -1; // return if can't get the mem
503 while ((*str) && (index < nz))
506 if (*str == '.') ++str;
509 if (my_isdigit(*str))
511 unsigned long number = 0;
513 // grab a digit token and convert it to a long int
514 while (my_isdigit(*str))
515 number = (number * 10) + *(str++) - '0';
517 // stuff the value into the array and bump the counter
518 temp[index++] = number;
520 // there must be a dot or end of string now
521 if ((*str) && (*str != '.'))
528 // check for other chars
529 if ((*str) && (*str != '.'))
531 // found String -> converting it into an oid
541 // copy until second $
542 while ((*str) && (*str != '$'))
544 temp[index] = (unsigned char)*str;
558 // there must be a dot or end of string now
559 if ((*str) && (*str != '.'))
567 // get some space for the real oid
568 dstOid->ptr = (SmiLPUINT32) new unsigned long[index];
569 // return if can't get the mem needed
576 // copy in the temp data
577 MEMCPY((SmiLPBYTE) dstOid->ptr,
579 (size_t) (index*sizeof(SmiUINT32)));
581 // set the len of the oid
591 //===============[Oid::OidCopy(source, destination) ]====================
593 int Oid::OidCopy(SmiLPOID srcOid, SmiLPOID dstOid) const
595 // check source len ! zero
596 if (srcOid->len == 0) return -1;
598 // copy source to destination
599 MEMCPY((SmiLPBYTE) dstOid->ptr,
600 (SmiLPBYTE) srcOid->ptr,
601 (size_t) (srcOid->len*sizeof(SmiUINT32)));
604 dstOid->len = srcOid->len;
605 return (int) srcOid->len;
609 //===============[Oid::nCompare(n, Oid) ]=================================
610 // compare the n leftmost values of two oids (left-to_right )
612 // self == Oid then return 0, they are equal
613 // self < Oid then return -1, <
614 // self > Oid then return 1, >
615 int Oid::nCompare(const unsigned long n,
618 unsigned long length = n;
619 bool reduced_len = false;
621 // If both oids are too short, decrease len
622 while ((smival.value.oid.len < length) && (o.smival.value.oid.len < length))
625 if (length == 0) return 0; // equal
627 // only compare for the minimal length
628 if (length > smival.value.oid.len)
630 length = smival.value.oid.len;
633 if (length > o.smival.value.oid.len)
635 length = o.smival.value.oid.len;
642 if (smival.value.oid.ptr[z] < o.smival.value.oid.ptr[z])
643 return -1; // less than
644 if (smival.value.oid.ptr[z] > o.smival.value.oid.ptr[z])
645 return 1; // greater than
649 // if we truncated the len then these may not be equal
652 if (smival.value.oid.len < o.smival.value.oid.len) return -1;
653 if (smival.value.oid.len > o.smival.value.oid.len) return 1;
658 //================[Oid::OidToStr ]=========================================
659 // convert an oid to a string
660 int Oid::OidToStr(const SmiOID *srcOid,
665 char szNumber[SNMPBUFFSIZE];
668 str[0] = 0; // init the string
670 // verify there is something to copy
671 if (srcOid->len == 0)
674 // loop through and build up a string
675 for (unsigned long index = 0; index < srcOid->len; ++index)
677 // convert data element to a string
678 cur_len = sprintf(szNumber, "%lu", srcOid->ptr[index]);
680 // verify len is not over
681 if (totLen + cur_len + 1 >= size)
684 // if not at begin, pad with a dot
688 // copy the string token into the main string
689 STRCPY(str + totLen, szNumber);
691 // adjust the total len
698 //================[ general Value = operator ]========================
699 SnmpSyntax& Oid::operator=(const SnmpSyntax &val)
701 if (this == &val) return *this; // protect against assignment from self
708 switch (val.get_syntax())
710 case sNMP_SYNTAX_OID:
711 set_data(((Oid &)val).smival.value.oid.ptr,
712 (unsigned int)((Oid &)val).smival.value.oid.len);
719 int Oid::get_asn1_length() const
721 int length = 1; // for first 2 subids
723 for (unsigned int i = 2; i < smival.value.oid.len; ++i)
725 unsigned long v = smival.value.oid.ptr[i];
727 if (v < 0x80) // 7 bits long subid
729 else if (v < 0x4000) // 14 bits long subid
731 else if (v < 0x200000) // 21 bits long subid
733 else if (v < 0x10000000) // 28 bits long subid
735 else // 32 bits long subid
741 else if (length < 256)
746 #ifdef SNMP_PP_NAMESPACE
747 }; // end of namespace Snmp_pp