]> git.stg.codes - ssmd.git/blob - 3rdparty/snmp++/src/octet.cpp
Initial adding
[ssmd.git] / 3rdparty / snmp++ / src / octet.cpp
1 /*_############################################################################
2   _## 
3   _##  octet.cpp  
4   _##
5   _##  SNMP++v3.2.25
6   _##  -----------------------------------------------
7   _##  Copyright (c) 2001-2010 Jochen Katz, Frank Fock
8   _##
9   _##  This software is based on SNMP++2.6 from Hewlett Packard:
10   _##  
11   _##    Copyright (c) 1996
12   _##    Hewlett-Packard Company
13   _##  
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. 
25   _##  
26   _##  Stuttgart, Germany, Thu Sep  2 00:07:47 CEST 2010 
27   _##  
28   _##########################################################################*/
29 /*===================================================================
30
31   Copyright (c) 1999
32   Hewlett-Packard Company
33
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.
44
45   O C T E T . C P P
46
47   OCTETSTR CLASS IMPLEMENTATION
48
49   DESIGN + AUTHOR:  Peter E Mellquist
50
51   DESCRIPTION:
52   This class is fully contained and does not rely on or any other
53   SNMP libraries. This class is portable across any platform
54   which supports C++.
55 =====================================================================*/
56 char octet_cpp_version[]="@(#) SNMP++ $Id: octet.cpp 1824 2010-08-29 19:47:08Z katz $";
57
58 #include "snmp_pp/octet.h"    // include definition for octet class
59 #include <ctype.h>    // for isprint() used by get_printable()
60 #include <stdio.h>    // for sprintf() used by get_printable_hex()
61 #include <string.h>   // for strlen() and memcpy()
62
63 #ifdef SNMP_PP_NAMESPACE
64 namespace Snmp_pp {
65 #endif
66
67 enum OctetStr::OutputType OctetStr::hex_output_type
68                                                = OctetStr::OutputHexAndClear;
69 char OctetStr::nonprintable_char = '.';
70
71 #ifdef __unix
72     char OctetStr::linefeed_chars[3] = "\n";
73 #else
74     char OctetStr::linefeed_chars[3] = "\r\n";
75 #endif // __unix
76
77
78 //============[ constructor using no arguments ]======================
79 OctetStr::OctetStr()
80   : output_buffer(0), output_buffer_len(0), m_changed(true), validity(true)
81 {
82   smival.syntax = sNMP_SYNTAX_OCTETS;
83   smival.value.string.ptr = 0;
84   smival.value.string.len = 0;
85 }
86
87 //============[ constructor using a  string ]=========================
88 OctetStr::OctetStr(const char *str)
89   : output_buffer(0), output_buffer_len(0), m_changed(true), validity(true)
90 {
91   smival.syntax = sNMP_SYNTAX_OCTETS;
92   smival.value.string.ptr = 0;
93   smival.value.string.len = 0;
94
95   size_t z;
96
97   // check for null string
98   if (!str || !((z = strlen(str))))
99     return;
100
101   // get mem needed
102   smival.value.string.ptr = (SmiLPBYTE) new unsigned char[z];
103
104   if (smival.value.string.ptr)
105   {
106     MEMCPY(smival.value.string.ptr, str, z);
107     smival.value.string.len = SAFE_INT_CAST(z);
108   }
109   else
110     validity = false;
111 }
112
113
114 //============[ constructor using an unsigned char * ]================
115 OctetStr::OctetStr(const unsigned char *str, unsigned long len)
116   : output_buffer(0), output_buffer_len(0), m_changed(true), validity(true)
117 {
118   smival.syntax = sNMP_SYNTAX_OCTETS;
119   smival.value.string.ptr = 0;
120   smival.value.string.len = 0;
121
122   if (!str || !len)  return;   // check for zero len
123
124   // get the mem needed
125   smival.value.string.ptr = (SmiLPBYTE) new unsigned char[len];
126
127   if (smival.value.string.ptr)
128   {
129     MEMCPY(smival.value.string.ptr, str, (size_t) len);
130     smival.value.string.len = len;
131   }
132   else
133     validity = false;
134 }
135
136 //============[ constructor using another octet object ]==============
137 OctetStr::OctetStr (const OctetStr &octet)
138   : output_buffer(0), output_buffer_len(0), m_changed(true), validity(true)
139 {
140   smival.syntax = sNMP_SYNTAX_OCTETS;
141   smival.value.string.ptr = 0;
142   smival.value.string.len = 0;
143
144   if (octet.smival.value.string.len == 0) return;  // check for zero len case
145
146   // must be a valid object
147   if (!octet.validity)
148   {
149     validity = false;
150     return;
151   }
152
153   // get the mem needed
154   smival.value.string.ptr = (SmiLPBYTE) new unsigned char[octet.smival.value.string.len];
155
156   if (smival.value.string.ptr)
157   {
158     MEMCPY(smival.value.string.ptr,
159            octet.smival.value.string.ptr,
160            (size_t) octet.smival.value.string.len);
161     smival.value.string.len = octet.smival.value.string.len;
162   }
163   else
164     validity = false;
165 }
166
167 //=============[ destructor ]=========================================
168 OctetStr::~OctetStr()
169 {
170   // if not empty, free it up
171   if (smival.value.string.ptr) delete [] smival.value.string.ptr;
172   smival.value.string.len = 0;
173   smival.value.string.ptr = 0;
174   if (output_buffer)           delete [] output_buffer;
175   output_buffer = 0;
176   output_buffer_len = 0;
177 }
178
179
180 //============[ set the data on an already constructed Octet ]============
181 void OctetStr::set_data(const unsigned char *str, unsigned long len)
182 {
183   // free up already used space
184   if (smival.value.string.ptr)
185   {
186     delete [] smival.value.string.ptr;
187     smival.value.string.ptr = 0;
188   }
189   smival.value.string.len = 0;
190   m_changed = true;
191
192   // check for zero len
193   if (!str || !len)
194   {
195     validity = true;
196     return;
197   }
198
199   // get the mem needed
200   smival.value.string.ptr = (SmiLPBYTE) new unsigned char[len];
201
202   if (smival.value.string.ptr)
203   {
204     MEMCPY(smival.value.string.ptr, str, len);
205     smival.value.string.len = len;
206     validity = true;
207   }
208   else
209     validity = false;
210 }
211
212 //=============[ assignment to a string operator overloaded ]=========
213 OctetStr& OctetStr::operator=(const char *str)
214 {
215   size_t nz;
216
217   // free up previous memory if needed
218   if (smival.value.string.ptr)
219   {
220     delete [] smival.value.string.ptr;
221     smival.value.string.ptr = 0;
222     smival.value.string.len = 0;
223   }
224
225   m_changed = true;
226
227   // if empty then we are done; get the string size
228   if (!str || !((nz = strlen(str))))
229   {
230     validity = true;
231     return *this;
232   }
233
234   // get memory needed
235   smival.value.string.ptr = (SmiLPBYTE) new unsigned char[nz];
236
237   if (smival.value.string.ptr)
238   {
239     MEMCPY(smival.value.string.ptr, str, nz);
240     smival.value.string.len = SAFE_INT_CAST(nz);
241     validity = true;
242   }
243   else
244     validity = false;
245
246   return *this;      // return self reference
247 }
248
249 //=============[ assignment to another oid object overloaded ]========
250 OctetStr& OctetStr::operator=(const OctetStr &octet)
251 {
252   if (this == &octet)  return *this; // protect against assignment from self
253
254   if (!octet.validity) return *this; // don't assign from invalid objs
255
256   set_data(octet.smival.value.string.ptr, octet.smival.value.string.len);
257
258   return *this;                // return self reference
259 }
260
261 //==============[ equivlence operator overloaded ]====================
262 int operator==(const OctetStr &lhs, const OctetStr &rhs)
263 {
264   if (lhs.smival.value.string.len != rhs.smival.value.string.len)
265     return false;
266   return (lhs.nCompare(rhs.smival.value.string.len, rhs) == 0);
267 }
268
269 //==============[ not equivlence operator overloaded ]================
270 int operator!=(const OctetStr &lhs, const OctetStr &rhs)
271 {
272   if (lhs.smival.value.string.len != rhs.smival.value.string.len)
273     return true;
274   return (lhs.nCompare(rhs.smival.value.string.len, rhs) != 0);
275 }
276
277 //==============[ less than < overloaded ]============================
278 int operator<(const OctetStr &lhs, const OctetStr &rhs)
279 {
280   int maxlen = lhs.smival.value.string.len > rhs.smival.value.string.len
281              ? lhs.smival.value.string.len : rhs.smival.value.string.len;
282   return (lhs.nCompare(maxlen, rhs) < 0);
283 }
284
285 //==============[ less than <= overloaded ]===========================
286 int operator<=(const OctetStr &lhs, const OctetStr &rhs)
287 {
288   int maxlen = lhs.smival.value.string.len > rhs.smival.value.string.len
289              ? lhs.smival.value.string.len : rhs.smival.value.string.len;
290   return (lhs.nCompare(maxlen, rhs) <= 0);
291 }
292
293 //===============[ greater than > overloaded ]========================
294 int operator>(const OctetStr &lhs, const OctetStr &rhs)
295 {
296   int maxlen = lhs.smival.value.string.len > rhs.smival.value.string.len
297              ? lhs.smival.value.string.len : rhs.smival.value.string.len;
298   return (lhs.nCompare(maxlen, rhs) > 0);
299 }
300
301 //===============[ greater than >= overloaded ]=======================
302 int operator>=(const OctetStr &lhs, const OctetStr &rhs)
303 {
304   int maxlen = lhs.smival.value.string.len > rhs.smival.value.string.len
305              ? lhs.smival.value.string.len : rhs.smival.value.string.len;
306   return (lhs.nCompare(maxlen, rhs) >=0);
307 }
308
309 //===============[ equivlence operator overloaded ]===================
310 int operator==(const OctetStr &lhs, const char *rhs)
311 {
312   OctetStr to(rhs);
313   if (lhs.smival.value.string.len != to.smival.value.string.len)
314     return false;
315   return (lhs.nCompare(to.smival.value.string.len, to) == 0);
316 }
317
318 //===============[ not equivlence operator overloaded ]===============
319 int operator!=(const OctetStr &lhs, const char *rhs)
320 {
321   OctetStr to(rhs);
322   if (lhs.smival.value.string.len != to.smival.value.string.len)
323     return true;
324   return (lhs.nCompare(to.smival.value.string.len, to) != 0);
325 }
326
327 //===============[ less than < operator overloaded ]==================
328 int operator<(const OctetStr &lhs, const char *rhs)
329 {
330   OctetStr to(rhs);
331   int maxlen = lhs.smival.value.string.len > to.smival.value.string.len
332              ? lhs.smival.value.string.len : to.smival.value.string.len;
333   return (lhs.nCompare(maxlen,to) < 0);
334 }
335
336 //===============[ less than <= operator overloaded ]=================
337 int operator<=(const OctetStr &lhs, const char *rhs)
338 {
339   OctetStr to(rhs);
340   int maxlen = lhs.smival.value.string.len > to.smival.value.string.len
341              ? lhs.smival.value.string.len : to.smival.value.string.len;
342   return (lhs.nCompare(maxlen, to) <= 0);
343 }
344
345 //===============[ greater than > operator overloaded ]===============
346 int operator>(const OctetStr &lhs, const char *rhs)
347 {
348   OctetStr to(rhs);
349   int maxlen = lhs.smival.value.string.len > to.smival.value.string.len
350              ? lhs.smival.value.string.len : to.smival.value.string.len;
351   return (lhs.nCompare(maxlen, to) > 0);
352 }
353
354 //===============[ greater than >= operator overloaded ]==============
355 int operator>=(const OctetStr &lhs, const char *rhs)
356 {
357   OctetStr to(rhs);
358   int maxlen = lhs.smival.value.string.len > to.smival.value.string.len
359              ? lhs.smival.value.string.len : to.smival.value.string.len;
360   return (lhs.nCompare(maxlen, to) >= 0);
361 }
362
363 //===============[ append operator, appends a string ]================
364 OctetStr& OctetStr::operator+=(const char *a)
365 {
366   unsigned char *tmp;
367   size_t slen, nlen;
368
369   // get len of string
370   if (!a || ((slen = strlen(a)) == 0))
371     return *this;
372
373   nlen = slen + (size_t) smival.value.string.len;  // total len of new octet
374   tmp = (SmiLPBYTE) new unsigned char[nlen];  // get mem needed
375
376   if (tmp)
377   {
378     // copy in the original 1st
379     MEMCPY(tmp, smival.value.string.ptr, smival.value.string.len);
380     // copy in the string
381     MEMCPY(tmp + smival.value.string.len, a, slen);
382     // delete the original
383     if (smival.value.string.ptr)
384       delete [] smival.value.string.ptr;
385     // point to the new one
386     smival.value.string.ptr = tmp;
387     smival.value.string.len = SAFE_INT_CAST(nlen);
388
389     m_changed = true;
390   }
391   return *this;
392 }
393
394 //================[ append one OctetStr to another ]==================
395 OctetStr& OctetStr::operator+=(const OctetStr& octet)
396 {
397   unsigned char *tmp;
398   size_t slen, nlen;
399
400   if (!octet.validity || !((slen = (size_t)octet.len())))
401     return *this;
402
403   nlen = slen + (size_t) smival.value.string.len;  // total len of new octet
404   tmp = (SmiLPBYTE) new unsigned char[nlen];  // get mem needed
405
406   if (tmp)
407   {
408     // copy in the original 1st
409     MEMCPY(tmp, smival.value.string.ptr, smival.value.string.len);
410     // copy in the string
411     MEMCPY(tmp + smival.value.string.len, octet.data(), slen);
412     // delete the original
413     if (smival.value.string.ptr )
414       delete [] smival.value.string.ptr;
415     // point to the new one
416     smival.value.string.ptr = tmp;
417     smival.value.string.len = SAFE_INT_CAST(nlen);
418
419     m_changed = true;
420   }
421   return *this;
422 }
423
424 //================[ appends a char ]==================================
425 OctetStr& OctetStr::operator+=(const unsigned char c)
426 {
427   unsigned char *tmp;
428
429   // get the memory needed plus one extra byte
430   tmp = (SmiLPBYTE) new unsigned char[smival.value.string.len + 1];
431
432   if (tmp)
433   {
434     MEMCPY(tmp, smival.value.string.ptr, smival.value.string.len);
435     tmp[smival.value.string.len] = c;   // assign in new byte
436
437     if (smival.value.string.ptr)        // delete the original
438       delete [] smival.value.string.ptr;
439
440     smival.value.string.ptr = tmp;      // point to new one
441     smival.value.string.len++;          // up the len
442
443     m_changed = true;
444   }
445   return *this;                           // return self reference
446 }
447
448 //================[ compare n elements of an Octet ]==================
449 int OctetStr::nCompare(const unsigned long n, const OctetStr &o) const
450 {
451   unsigned long n_max;
452   unsigned long w,str_len;
453
454   if (n == 0) return 0; // Nothing to compare, strings are equal
455
456   // both are empty, they are equal
457   if ((smival.value.string.len == 0) && (o.smival.value.string.len == 0))
458     return 0;  // equal
459
460   // self is empty and param has something
461   if ((smival.value.string.len == 0) && (o.smival.value.string.len > 0))
462     return -1;
463
464   // self has something and param has nothing
465   if ((smival.value.string.len > 0) && (o.smival.value.string.len == 0))
466     return 1;
467
468   // now: n > 0; this.len > 0; o.len > 0 !!!
469
470   // pick the Min of n, this and the param len
471   // this is the maximum # to iterate a search
472   str_len = smival.value.string.len < o.smival.value.string.len
473             ? smival.value.string.len : o.smival.value.string.len;
474   w = (n <= str_len) ? n : str_len;
475
476   unsigned long z = 0;
477   while (z < w)
478   {
479     if (smival.value.string.ptr[z] < o.smival.value.string.ptr[z])
480       return -1;                                // less than
481     if (smival.value.string.ptr[z] > o.smival.value.string.ptr[z])
482       return 1;                         // greater than
483     z++;
484   }
485
486   // now: z == w > 0
487   // set n_max to min(n, max(len of strings))
488   n_max = smival.value.string.len > o.smival.value.string.len
489           ? smival.value.string.len : o.smival.value.string.len;
490   if (n< n_max) n_max = n;
491
492   if (w < n_max) // ==> we have compared too few bytes
493   {
494     if (smival.value.string.len < o.smival.value.string.len)
495       return -1;
496     else
497       return 1;
498   }
499   return 0;
500 }
501
502 //================[ ASCII format return ]=============================
503 const char *OctetStr::get_printable() const
504 {
505   if ((m_changed == false) &&
506       (output_last_function == OutputFunctionDefault))
507     return output_buffer;
508
509   for (unsigned long i=0; i < smival.value.string.len; i++)
510   {
511     if ((smival.value.string.ptr[i] != '\r')&&
512         (smival.value.string.ptr[i] != '\n')&&
513         (isprint((int) (smival.value.string.ptr[i]))==0))
514       switch (hex_output_type)
515       {
516         case OutputClear:        return get_printable_clear();
517         case OutputHexAndClear:
518         case OutputHex:
519         default:                 return get_printable_hex();
520       }
521   }
522
523   OctetStr *ncthis = PP_CONST_CAST(OctetStr*, this);
524   if (output_buffer_len < smival.value.string.len + 1)
525   {
526     if (output_buffer) delete [] ncthis->output_buffer;
527
528     ncthis->output_buffer = new char[smival.value.string.len + 1];      
529     if (!ncthis->output_buffer)
530     {
531       ncthis->output_buffer_len = 0;
532       return output_buffer;
533     }
534     ncthis->output_buffer_len = smival.value.string.len + 1;
535   }
536   if (smival.value.string.len)
537     MEMCPY(ncthis->output_buffer,
538            smival.value.string.ptr, (unsigned int) smival.value.string.len);
539   ncthis->output_buffer[smival.value.string.len] = '\0';
540
541   ncthis->m_changed = false;
542   ncthis->output_last_function = OutputFunctionDefault;
543
544   return output_buffer;
545 }
546
547 //================[ ASCII format return ]=============================
548 const char *OctetStr::get_printable_clear() const
549 {
550   if ((m_changed == false) &&
551       (output_last_np_char == nonprintable_char) &&
552       (output_last_function == OutputFunctionClear))
553     return output_buffer;
554
555   OctetStr *ncthis = PP_CONST_CAST(OctetStr*, this);
556   if (output_buffer_len < smival.value.string.len + 1)
557   {
558     if (output_buffer) delete [] ncthis->output_buffer;
559
560     ncthis->output_buffer = new char[smival.value.string.len + 1];      
561     if (!ncthis->output_buffer)
562     {
563       ncthis->output_buffer_len = 0;
564       return output_buffer;
565     }
566     ncthis->output_buffer_len = smival.value.string.len + 1;
567   }
568
569   if (smival.value.string.len)
570   {
571     for (unsigned long i=0; i < smival.value.string.len; i++)
572     {
573       if (isprint((int) (smival.value.string.ptr[i]))==0)
574         ncthis->output_buffer[i] = nonprintable_char;
575       else
576         ncthis->output_buffer[i] = smival.value.string.ptr[i];
577     }
578   }
579
580   ncthis->output_buffer[smival.value.string.len] = '\0';
581
582   ncthis->output_last_np_char = nonprintable_char;
583   ncthis->m_changed = false;
584   ncthis->output_last_function = OutputFunctionClear;
585
586   return output_buffer;
587 }
588
589
590 //================[ general Value = operator ]========================
591 SnmpSyntax& OctetStr::operator=(const SnmpSyntax &val)
592 {
593   if (this == &val) return *this;  // protect against assignment from self
594
595   // blow away the old value
596   if (smival.value.string.ptr)
597   {
598     delete [] smival.value.string.ptr;
599     smival.value.string.ptr = 0;
600   }
601   smival.value.string.len = 0;
602   validity = false;
603
604   if (val.valid()){
605     switch (val.get_syntax()){
606       case sNMP_SYNTAX_OPAQUE:
607       case sNMP_SYNTAX_BITS:
608       case sNMP_SYNTAX_OCTETS:
609       case sNMP_SYNTAX_IPADDR:
610         set_data(((OctetStr &)val).smival.value.string.ptr,
611                  ((OctetStr &)val).smival.value.string.len);
612         break;
613     }
614   }
615   m_changed = true;
616   return *this;
617 }
618
619 #define ATOI(x)  if      ((x >= 48) && (x <= 57)) x = x-48; /* 0-9 */ \
620                  else if ((x >= 65) && (x <= 70)) x = x-55; /* A-F */ \
621                  else if ((x >= 97) && (x <=102)) x = x-87; /* a-f */ \
622                  else x = 0
623
624 //=======[ create an octet string from a hex string ]===================
625 OctetStr OctetStr::from_hex_string(const OctetStr &hex_string)
626 {
627   OctetStr val;
628   unsigned int p;
629   unsigned int hex_len = 0;
630
631   // make sure the string has at least one byte
632   if (hex_string.len() == 0) return val;
633
634   // allocate max needed space for copy without spaces
635   unsigned char *hex, *hex_ptr;
636   hex = hex_ptr = new unsigned char[hex_string.len()];
637   if (!hex) return val;
638
639   // delete spaces
640   const unsigned char *ptr = hex_string.smival.value.string.ptr;
641   for (p = hex_string.len(); p > 0; p--)
642   {
643     unsigned char c = *ptr++;
644     if (c != ' ')
645     {
646       *hex_ptr++ = c;
647       ++hex_len;
648     }
649   }
650
651   // leading 0 may be omitted
652   if (hex_len % 2)
653   {
654     unsigned char c = hex[0];
655     ATOI(c);
656     val += c;
657     p = 1;
658   }
659   else
660   {
661     p = 0;
662   }
663
664   while (p < hex_len)
665   {
666     unsigned char c = hex[p++];
667     unsigned char d = hex[p++];
668
669     ATOI(c);
670     ATOI(d);
671     val += (c*16 + d);
672   }
673   delete[] hex;
674   return val;
675 }
676
677 #undef ATOI
678
679 //================[ format the output into hex ]========================
680 const char *OctetStr::get_printable_hex() const
681 {
682   if ((m_changed == false) && (output_last_type == hex_output_type) &&
683       (output_last_np_char == nonprintable_char) &&
684       (output_last_function == OutputFunctionHex))
685     return output_buffer;
686
687   int cnt;
688   char char_buf[80];              // holds ASCII representation of data
689   char *buf_ptr;                  // pointer into ASCII listing 
690   char *line_ptr;                 // pointer into Hex listing
691   unsigned int  storageNeeded;    // how much space do we need ?
692   int  local_len = (int) smival.value.string.len;
693   unsigned char *bytes = smival.value.string.ptr;
694
695   storageNeeded = (unsigned int) ((smival.value.string.len/16)+1) * 72 + 1;
696   OctetStr *ncthis = PP_CONST_CAST(OctetStr*, this);
697
698   if (output_buffer_len < storageNeeded)
699   {
700     if (output_buffer)  delete [] ncthis->output_buffer;
701
702     ncthis->output_buffer = new char[storageNeeded];
703     if (!ncthis->output_buffer)
704     {
705       ncthis->output_buffer_len = 0;
706       return output_buffer;
707     }
708     ncthis->output_buffer_len = storageNeeded;
709   }
710
711   line_ptr = ncthis->output_buffer;
712
713   /*----------------------------------------*/
714   /* processing loop for entire data buffer */
715   /*----------------------------------------*/
716   while (local_len > 0)
717   {
718     cnt      = 16;        /* print 16 bytes per line */
719     buf_ptr  = char_buf;
720     sprintf(line_ptr, "  ");
721     line_ptr += 2;  /* indent */
722
723     /*-----------------------*/
724     /* process a single line */
725     /*-----------------------*/
726     while (cnt-- > 0 && local_len-- > 0)
727     {
728       sprintf(line_ptr, "%2.2X ", *bytes);
729
730       line_ptr +=3;   /* the display of a byte always 3 chars long */
731       if (isprint(*bytes))
732         *buf_ptr++ = *bytes;
733       else
734         *buf_ptr++ = nonprintable_char;
735       ++bytes;
736     }
737     ++cnt;
738     *buf_ptr = 0; // null terminate string
739
740     /*----------------------------------------------------------*/
741     /* this is to make sure that the ASCII displays line up for */
742     /* incomplete lines of hex                                  */
743     /*----------------------------------------------------------*/
744     while (cnt-- > 0)
745     {
746       *line_ptr++ = ' ';
747       *line_ptr++ = ' ';
748       *line_ptr++ = ' ';
749     }
750
751     /*------------------------------------------*/
752     /* append the ASCII display to the Hex line */
753     /*------------------------------------------*/
754     if (hex_output_type == OutputHex)
755       char_buf[0] = 0;
756
757     sprintf(line_ptr,"   %s%s", char_buf, linefeed_chars);
758     line_ptr += 3 + strlen(char_buf) + strlen(linefeed_chars);
759   }
760
761   ncthis->output_last_type = hex_output_type;
762   ncthis->output_last_np_char = nonprintable_char;
763   ncthis->m_changed = false;
764   ncthis->output_last_function = OutputFunctionHex;
765
766   return output_buffer;
767 }
768
769
770 //==============[ Null out the contents of the string ]===================
771 void OctetStr::clear()
772 {
773   if (smival.value.string.len > 0)
774   {
775     memset(smival.value.string.ptr, 0, smival.value.string.len);
776     smival.value.string.len = 0;
777   }
778
779   if (output_buffer)
780     memset(output_buffer, 0, output_buffer_len);
781   m_changed = true;
782 }
783
784 //============[Return the space needed for serialization]=================
785 int OctetStr::get_asn1_length() const
786 {
787   if (smival.value.string.len < 0x80)
788     return smival.value.string.len + 2;
789   else if (smival.value.string.len < 0x100)
790     return smival.value.string.len + 3;
791   else if (smival.value.string.len < 0x10000)
792     return smival.value.string.len + 4;
793   else if (smival.value.string.len < 0x1000000)
794     return smival.value.string.len + 5;
795   return smival.value.string.len + 6; // should be safe for some time...
796 }
797
798 //========[Set the character for linefeeds in get_printable() functions]====
799 bool OctetStr::set_linefeed_chars(const char* lf_chars)
800 {
801     if (!lf_chars) return false;
802     if (strlen(lf_chars) > 2) return false;
803
804     linefeed_chars[2] = 0;
805     linefeed_chars[1] = lf_chars[1];
806     linefeed_chars[0] = lf_chars[0];
807
808     return true;
809 }
810
811 //===============[ append or shorten the data buffer ]================
812 bool OctetStr::set_len(const unsigned long new_len)
813 {
814   unsigned char *tmp;
815
816   if (new_len <= smival.value.string.len)
817   {
818     smival.value.string.len = new_len;
819     m_changed = true;
820
821     if (new_len == 0)
822     {
823       if (smival.value.string.ptr) delete [] smival.value.string.ptr;
824       smival.value.string.ptr = 0;
825     }
826
827     return true;
828   }
829
830   tmp = (SmiLPBYTE) new unsigned char[new_len];  // get mem needed
831
832   if (!tmp) return false;
833
834   if (smival.value.string.ptr)
835     MEMCPY(tmp, smival.value.string.ptr, smival.value.string.len);
836   memset(tmp + smival.value.string.len, 0, new_len - smival.value.string.len);
837   if (smival.value.string.ptr)
838     delete [] smival.value.string.ptr;
839   smival.value.string.ptr = tmp;
840   smival.value.string.len = new_len;
841
842   m_changed = true;
843
844   return true;
845 }
846
847
848
849 #ifdef SNMP_PP_NAMESPACE
850 }; // end of namespace Snmp_pp
851 #endif