2 //=============================================================================
6 * Implements the SMI Octet datatype (RFC 1155)
7 * This class is fully contained and does not rely on or any other
8 * SNMP libraries. Ported to ACE by Michael MacFaden mrm@cisco.com
10 * @author Peter E Mellquist
12 //=============================================================================
14 /*===================================================================
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 #include "asnmp/octet.h" // include definition for octet class
31 #include "ace/OS_Memory.h"
32 #include "ace/OS_NS_string.h"
33 #include "ace/OS_NS_stdio.h"
34 #include "ace/OS_NS_ctype.h"
35 #include "ace/os_include/os_ctype.h"
37 //============[ syntax type ]=========================================
38 SmiUINT32
OctetStr::get_syntax()
40 return sNMP_SYNTAX_OCTETS
;
44 void init_octet_smi(SmiVALUE
& smi
)
46 smi
.syntax
= sNMP_SYNTAX_OCTETS
;
47 smi
.value
.string
.ptr
= 0;
48 smi
.value
.string
.len
= 0;
52 void reset_octet_smi(SmiVALUE
& smi
)
54 delete [] smi
.value
.string
.ptr
;
55 smi
.value
.string
.ptr
= 0;
56 smi
.value
.string
.len
= 0;
60 int copy_octet_smi(SmiVALUE
& smi
, int size
, const char *src
, int& valid_flag
)
64 if (smi
.value
.string
.ptr
)
65 delete [] smi
.value
.string
.ptr
;
67 ACE_NEW_RETURN(smi
.value
.string
.ptr
, SmiBYTE
[size
], 1);
68 ACE_OS::memcpy( smi
.value
.string
.ptr
, src
, size
);
69 smi
.value
.string
.len
= size
;
74 //============[ default constructor ]=========================
75 OctetStr::OctetStr( const char * string
, long size
):
76 output_buffer(0), validity(0)
78 init_octet_smi(smival
);
80 // check for null string
84 if (size
== -1) // calc if no length given - assume c style string
85 size
= ACE_OS::strlen( string
);
87 copy_octet_smi(smival
, size
, string
, validity
);
91 //============[ set the data on an already constructed Octet ]============
92 // TODO: should return status since it can fail in so many places
93 void OctetStr::set_data( const SmiBYTE
* string
, long size
)
95 // invalid args, set octetStr to not valid
96 if ( !string
|| !size
) {
101 // assume non-zero terminated string
102 if (size
== -1) // calc if no length given - assume c style string
103 size
= ACE_OS::strlen( (char *)string
);
105 // free up already used space
106 if ( smival
.value
.string
.ptr
) {
107 reset_octet_smi(smival
);
109 smival
.value
.string
.len
= 0;
112 copy_octet_smi(smival
, size
, (const char *)string
, validity
);
115 //============[ constructor using another octet object ]==============
116 OctetStr::OctetStr ( const OctetStr
&octet
):
117 SnmpSyntax (octet
), output_buffer(0), validity(1)
119 init_octet_smi(smival
);
120 // check for zero len case
121 if ( octet
.smival
.value
.string
.len
== 0) {
125 // must be a valid object
126 if ( octet
.validity
== 0) {
131 // get the mem needed
132 copy_octet_smi(smival
, octet
.smival
.value
.string
.len
,
133 (const char *)octet
.smival
.value
.string
.ptr
, validity
);
136 //=============[ destructor ]=========================================
137 OctetStr::~OctetStr()
139 reset_octet_smi(smival
);
140 delete [] output_buffer
;
144 //=============[ assignment to a string operator overloaded ]=========
145 OctetStr
& OctetStr::operator=( const char *string
)
147 // get the string size
150 // free up previous memory if needed
151 if ( smival
.value
.string
.ptr
) {
152 reset_octet_smi(smival
);
155 // if empty then we are done
156 if (!string
|| !(nz
= ACE_OS::strlen( string
))) {
162 copy_octet_smi(smival
, nz
, string
, validity
);
166 //=============[ assignment to another oid object overloaded ]========
167 OctetStr
& OctetStr::operator=( const OctetStr
&octet
)
169 // protect against assignment from self
170 if ( this == &octet
)
173 // don't assign from invalid objs
174 if (!octet
.validity
) {
178 // free up previous memory if needed
179 if ( smival
.value
.string
.len
) {
180 reset_octet_smi(smival
);
183 if (!octet
.smival
.value
.string
.len
) {
189 copy_octet_smi(smival
, octet
.smival
.value
.string
.len
,
190 (const char*) octet
.smival
.value
.string
.ptr
, validity
);
191 return *this; // return self reference
194 //==============[ equivlence operator overloaded ]====================
195 bool operator==( const OctetStr
&lhs
, const OctetStr
&rhs
)
197 if( lhs
.left_comparison( rhs
.smival
.value
.string
.len
, rhs
)==0)
203 //==============[ not equivlence operator overloaded ]================
204 bool operator!=( const OctetStr
&lhs
, const OctetStr
&rhs
)
206 if( lhs
.left_comparison( rhs
.smival
.value
.string
.len
, rhs
)!=0)
212 //==============[ less than < overloaded ]============================
213 bool operator<( const OctetStr
&lhs
, const OctetStr
&rhs
)
215 if( lhs
.left_comparison( rhs
.smival
.value
.string
.len
, rhs
)<0)
221 //==============[ less than <= overloaded ]===========================
222 bool operator<=( const OctetStr
&lhs
, const OctetStr
&rhs
)
224 if(( lhs
.left_comparison( rhs
.smival
.value
.string
.len
, rhs
)<0) ||
225 ( lhs
.left_comparison( rhs
.smival
.value
.string
.len
, rhs
)==0))
231 //===============[ greater than > overloaded ]========================
232 bool operator>( const OctetStr
&lhs
, const OctetStr
&rhs
)
234 if( lhs
.left_comparison( rhs
.smival
.value
.string
.len
, rhs
)>0)
240 //===============[ greater than >= overloaded ]=======================
241 bool operator>=( const OctetStr
&lhs
, const OctetStr
&rhs
)
243 if(( lhs
.left_comparison( rhs
.smival
.value
.string
.len
, rhs
)>0) ||
244 ( lhs
.left_comparison( rhs
.smival
.value
.string
.len
, rhs
)==0))
250 //===============[ equivlence operator overloaded ]===================
251 bool operator==( const OctetStr
&lhs
,const char *rhs
)
254 if( lhs
.left_comparison( to
.smival
.value
.string
.len
,to
)==0)
260 //===============[ not equivlence operator overloaded ]===============
261 bool operator!=( const OctetStr
&lhs
,const char *rhs
)
264 if ( lhs
.left_comparison( to
.smival
.value
.string
.len
,to
)!=0)
270 //===============[ less than < operator overloaded ]==================
271 bool operator<( const OctetStr
&lhs
,const char *rhs
)
274 if ( lhs
.left_comparison( to
.smival
.value
.string
.len
,to
)<0)
280 //===============[ less than <= operator overloaded ]=================
281 bool operator<=( const OctetStr
&lhs
,char *rhs
)
284 if (( lhs
.left_comparison( to
.smival
.value
.string
.len
,to
)<0) ||
285 ( lhs
.left_comparison( to
.smival
.value
.string
.len
,to
)==0))
291 //===============[ greater than > operator overloaded ]===============
292 bool operator>( const OctetStr
&lhs
,const char *rhs
)
295 if ( lhs
.left_comparison( to
.smival
.value
.string
.len
,to
)>0)
301 //===============[ greater than >= operator overloaded ]==============
302 bool operator>=( const OctetStr
&lhs
,const char *rhs
)
305 if (( lhs
.left_comparison( to
.smival
.value
.string
.len
,to
)>0) ||
306 ( lhs
.left_comparison( to
.smival
.value
.string
.len
,to
)==0))
312 //===============[ append operator, appends a string ]================
313 OctetStr
& OctetStr::operator+=( const char *a
)
315 SmiBYTE
*tmp
; // temp pointer
319 if ( !a
|| ((slen
= ACE_OS::strlen( a
)) == 0))
322 // total len of octet
323 nlen
= slen
+ (size_t) smival
.value
.string
.len
;
324 ACE_NEW_RETURN(tmp
, SmiBYTE
[ nlen
], *this);
325 ACE_OS::memcpy ( tmp
, smival
.value
.string
.ptr
,
326 (size_t) smival
.value
.string
.len
);
327 ACE_OS::memcpy( tmp
+ smival
.value
.string
.len
, a
, (size_t) slen
);
328 // delete the original
329 if ( smival
.value
.string
.ptr
)
330 reset_octet_smi(smival
);
331 smival
.value
.string
.ptr
= tmp
;
332 smival
.value
.string
.len
= nlen
;
336 //================[ append one OctetStr to another ]==================
337 OctetStr
& OctetStr::operator+=( const OctetStr
& octetstr
)
339 SmiBYTE
*tmp
; // temp pointer
342 if (!octetstr
.validity
||
343 !(slen
= (size_t)octetstr
.length()))
346 // total len of octet
347 nlen
= slen
+ (size_t) smival
.value
.string
.len
;
349 ACE_NEW_RETURN(tmp
, SmiBYTE
[ nlen
], *this);
350 ACE_OS::memcpy ( tmp
, smival
.value
.string
.ptr
,
351 (size_t) smival
.value
.string
.len
);
352 ACE_OS::memcpy( tmp
+ smival
.value
.string
.len
, octetstr
.data(),
354 if ( smival
.value
.string
.ptr
)
355 reset_octet_smi(smival
);
356 smival
.value
.string
.ptr
= tmp
;
357 smival
.value
.string
.len
= nlen
;
361 //================[ appends an int ]==================================
362 OctetStr
& OctetStr::operator+=( const char c
)
365 // get the memory needed plus one extra byte
366 ACE_NEW_RETURN(tmp
, SmiBYTE
[ smival
.value
.string
.len
+ 1], *this);
367 ACE_OS::memcpy ( tmp
, smival
.value
.string
.ptr
,
368 (size_t) smival
.value
.string
.len
); // len of original
369 tmp
[ smival
.value
.string
.len
] = c
; // assign in byte
370 if ( smival
.value
.string
.ptr
) // delete the original
371 reset_octet_smi(smival
);
373 smival
.value
.string
.ptr
= tmp
; // point to one
374 smival
.value
.string
.len
++; // up the len
379 //================[ compare n elements of an Octet ]==================
380 int OctetStr::left_comparison( const long n
, const OctetStr
&o
) const
384 // both are empty, they are equal
385 if (( smival
.value
.string
.len
== 0) &&
386 ( o
.smival
.value
.string
.len
== 0))
389 // self is empty and param has something
390 if (( smival
.value
.string
.len
== 0) &&
391 ( o
.smival
.value
.string
.len
>0) &&
395 // self has something and param has nothing
396 if (( smival
.value
.string
.len
> 0) &&
397 ( o
.smival
.value
.string
.len
==0) &&
402 if (( smival
.value
.string
.len
== 0) &&
403 ( o
.smival
.value
.string
.len
> 0) &&
407 // pick the Min of n, this and the param len
408 // this is the maximum # to iterate a search
409 w
= smival
.value
.string
.len
< o
.smival
.value
.string
.len
410 ? smival
.value
.string
.len
: o
.smival
.value
.string
.len
;
415 if ( smival
.value
.string
.ptr
[z
] < o
.smival
.value
.string
.ptr
[z
])
416 return -1; // less than
417 if ( smival
.value
.string
.ptr
[z
] > o
.smival
.value
.string
.ptr
[z
])
418 return 1; // greater than
423 ( smival
.value
.string
.len
== 0) &&
424 ( o
.smival
.value
.string
.len
> 0))
428 ( o
.smival
.value
.string
.len
== 0) &&
429 ( smival
.value
.string
.len
> 0))
435 //================[ return the length of the oid ]=======================
436 size_t OctetStr::length() const
438 return (size_t) smival
.value
.string
.len
;
441 //================[ operator[]: access as if array ]==================
442 SmiBYTE
& OctetStr::operator[]( int position
)
444 return smival
.value
.string
.ptr
[position
];
447 //===============[ reuturns pointer to internal data ]===============
448 SmiBYTE
* OctetStr::data() const
450 return smival
.value
.string
.ptr
;
453 //================[ returns validity ]================================
454 int OctetStr::valid() const
459 //================[ clone() ]=========================================
460 SnmpSyntax
* OctetStr::clone() const
462 OctetStr
*tmp
= new OctetStr(*this);
463 return ( SnmpSyntax
*) tmp
;
466 //================[ ASCII format return ]=============================
467 const char * OctetStr::to_string()
469 for ( unsigned long i
=0; i
< smival
.value
.string
.len
; i
++) {
470 if (( smival
.value
.string
.ptr
[i
] != '\r')&&
471 ( smival
.value
.string
.ptr
[i
] != '\n')&&
472 (ACE_OS::ace_isprint((int) (smival
.value
.string
.ptr
[i
]))==0))
473 return(to_string_hex());
476 if ( output_buffer
!= 0)
477 delete [] output_buffer
;
479 ACE_NEW_RETURN(output_buffer
, char[smival
.value
.string
.len
+ 1], "");
480 if (smival
.value
.string
.len
)
481 ACE_OS::memcpy(output_buffer
, smival
.value
.string
.ptr
,
482 (int) smival
.value
.string
.len
);
483 output_buffer
[smival
.value
.string
.len
] = '\0';
484 return output_buffer
;
488 //================[ general Value = operator ]========================
489 SnmpSyntax
& OctetStr::operator=( SnmpSyntax
&val
)
491 // protect against assignment from self
495 // blow away the old value
497 if (smival
.value
.string
.ptr
) {
498 reset_octet_smi(smival
);
500 smival
.value
.string
.len
= 0;
502 switch (val
.get_syntax()) {
503 case sNMP_SYNTAX_OCTETS
:
504 case sNMP_SYNTAX_IPADDR
:
505 set_data( ((OctetStr
&)val
).smival
.value
.string
.ptr
,
506 ((OctetStr
&)val
).smival
.value
.string
.len
);
513 //================[ format the output into hex ]========================
514 const char *OctetStr::to_string_hex()
517 char char_buf
[80]; // holds ASCII representation of data
518 char *buf_ptr
; // pointer into ASCII listing
519 char *line_ptr
; // pointer into Hex listing
520 int storageNeeded
; // how much space do we need ?
521 int local_len
= (int) smival
.value
.string
.len
;
522 SmiBYTE
*bytes
= smival
.value
.string
.ptr
;
525 storageNeeded
= (int) ((smival
.value
.string
.len
/16)+1) * 72 + 1;
527 if ( output_buffer
!= 0)
528 delete [] output_buffer
;
530 ACE_NEW_RETURN(output_buffer
, char[storageNeeded
], "");
532 line_ptr
= output_buffer
;
534 /*----------------------------------------*/
535 /* processing loop for entire data buffer */
536 /*----------------------------------------*/
537 while (local_len
> 0) {
538 cnt
= 16; /* print 16 bytes per line */
540 ACE_OS::sprintf(line_ptr
, " ");
541 line_ptr
+= 2; /* indent */
543 /*-----------------------*/
544 /* process a single line */
545 /*-----------------------*/
546 while (cnt
-- > 0 && local_len
-- > 0) {
547 ACE_OS::sprintf(line_ptr
, "%2.2X ", *bytes
);
549 line_ptr
+=3; /* the display of a byte always 3 chars long */
550 if (ACE_OS::ace_isprint(*bytes
))
551 ACE_OS::sprintf(buf_ptr
, "%c", *bytes
);
553 ACE_OS::sprintf(buf_ptr
, ".");
559 /*----------------------------------------------------------*/
560 /* this is to make sure that the ASCII displays line up for */
561 /* incomplete lines of hex */
562 /*----------------------------------------------------------*/
564 ACE_OS::sprintf(line_ptr
," ");
568 /*------------------------------------------*/
569 /* append the ASCII display to the Hex line */
570 /*------------------------------------------*/
572 // TODO: verify ACE_OS:: on NT works like this or not
574 #if defined(ACE_WIN32)
575 const char *fmt
= " %s\r\n";
577 const char *fmt
= " %s\n";
580 ACE_OS::sprintf(line_ptr
, fmt
, char_buf
);
581 line_ptr
+= 3 + ACE_OS::strlen(char_buf
);
584 return output_buffer
;