octet.cpp
上传用户:ets1996
上传日期:2014-09-30
资源大小:353k
文件大小:24k
源码类别:

SNMP编程

开发平台:

Visual C++

  1. /*_############################################################################
  2.   _## 
  3.   _##  octet.cpp  
  4.   _##
  5.   _##  SNMP++v3.2.22
  6.   _##  -----------------------------------------------
  7.   _##  Copyright (c) 2001-2007 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, Wed May  2 23:22:30 CEST 2007 
  27.   _##  
  28.   _##########################################################################*/
  29. /*===================================================================
  30.   Copyright (c) 1999
  31.   Hewlett-Packard Company
  32.   ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
  33.   Permission to use, copy, modify, distribute and/or sell this software
  34.   and/or its documentation is hereby granted without fee. User agrees
  35.   to display the above copyright notice and this license notice in all
  36.   copies of the software and any documentation of the software. User
  37.   agrees to assume all liability for the use of the software; Hewlett-Packard
  38.   makes no representations about the suitability of this software for any
  39.   purpose. It is provided "AS-IS" without warranty of any kind,either express
  40.   or implied. User hereby grants a royalty-free license to any and all
  41.   derivatives based upon this software code base.
  42.   O C T E T . C P P
  43.   OCTETSTR CLASS IMPLEMENTATION
  44.   DESIGN + AUTHOR:  Peter E Mellquist
  45.   LANGUAGE:         ANSI C++
  46.   DESCRIPTION:
  47.   This class is fully contained and does not rely on or any other
  48.   SNMP libraries. This class is portable across any platform
  49.   which supports C++.
  50. =====================================================================*/
  51. char octet_cpp_version[]="@(#) SNMP++ $Id: octet.cpp 248 2006-03-25 11:46:19Z katz $";
  52. #include "snmp_pp/octet.h"    // include definition for octet class
  53. #include <ctype.h>    // for isprint() used by get_printable()
  54. #include <stdio.h>    // for sprintf() used by get_printable_hex()
  55. #include <string.h>   // for strlen() and memcpy()
  56. #ifdef SNMP_PP_NAMESPACE
  57. namespace Snmp_pp {
  58. #endif
  59. enum OctetStr::OutputType OctetStr::hex_output_type
  60.                                                = OctetStr::OutputHexAndClear;
  61. char OctetStr::nonprintable_char = '.';
  62. #ifdef __unix
  63.     char OctetStr::linefeed_chars[3] = "n";
  64. #else
  65.     char OctetStr::linefeed_chars[3] = "rn";
  66. #endif // __unix
  67. //============[ constructor using no arguments ]======================
  68. OctetStr::OctetStr()
  69.   : output_buffer(0), output_buffer_len(0), m_changed(true), validity(true)
  70. {
  71.   smival.syntax = sNMP_SYNTAX_OCTETS;
  72.   smival.value.string.ptr = 0;
  73.   smival.value.string.len = 0;
  74. }
  75. //============[ constructor using a  string ]=========================
  76. OctetStr::OctetStr(const char *str)
  77.   : output_buffer(0), output_buffer_len(0), m_changed(true), validity(true)
  78. {
  79.   smival.syntax = sNMP_SYNTAX_OCTETS;
  80.   smival.value.string.ptr = 0;
  81.   smival.value.string.len = 0;
  82.   size_t z;
  83.   // check for null string
  84.   if (!str || !(z = strlen(str)))
  85.     return;
  86.   // get mem needed
  87.   smival.value.string.ptr = (SmiLPBYTE) new unsigned char[z];
  88.   if (smival.value.string.ptr)
  89.   {
  90.     MEMCPY(smival.value.string.ptr, str, z);
  91.     smival.value.string.len = SAFE_INT_CAST(z);
  92.   }
  93.   else
  94.     validity = false;
  95. }
  96. //============[ constructor using an unsigned char * ]================
  97. OctetStr::OctetStr(const unsigned char *str, unsigned long len)
  98.   : output_buffer(0), output_buffer_len(0), m_changed(true), validity(true)
  99. {
  100.   smival.syntax = sNMP_SYNTAX_OCTETS;
  101.   smival.value.string.ptr = 0;
  102.   smival.value.string.len = 0;
  103.   if (!str || !len)  return;   // check for zero len
  104.   // get the mem needed
  105.   smival.value.string.ptr = (SmiLPBYTE) new unsigned char[len];
  106.   if (smival.value.string.ptr)
  107.   {
  108.     MEMCPY(smival.value.string.ptr, str, (size_t) len);
  109.     smival.value.string.len = len;
  110.   }
  111.   else
  112.     validity = false;
  113. }
  114. //============[ constructor using another octet object ]==============
  115. OctetStr::OctetStr (const OctetStr &octet)
  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.   if (octet.smival.value.string.len == 0) return;  // check for zero len case
  122.   // must be a valid object
  123.   if (!octet.validity)
  124.   {
  125.     validity = false;
  126.     return;
  127.   }
  128.   // get the mem needed
  129.   smival.value.string.ptr = (SmiLPBYTE) new unsigned char[octet.smival.value.string.len];
  130.   if (smival.value.string.ptr)
  131.   {
  132.     MEMCPY(smival.value.string.ptr,
  133.    octet.smival.value.string.ptr,
  134.    (size_t) octet.smival.value.string.len);
  135.     smival.value.string.len = octet.smival.value.string.len;
  136.   }
  137.   else
  138.     validity = false;
  139. }
  140. //=============[ destructor ]=========================================
  141. OctetStr::~OctetStr()
  142. {
  143.   // if not empty, free it up
  144.   if (smival.value.string.ptr) delete [] smival.value.string.ptr;
  145.   smival.value.string.len = 0;
  146.   smival.value.string.ptr = 0;
  147.   if (output_buffer)           delete [] output_buffer;
  148.   output_buffer = 0;
  149.   output_buffer_len = 0;
  150. }
  151. //============[ set the data on an already constructed Octet ]============
  152. void OctetStr::set_data(const unsigned char *str, unsigned long len)
  153. {
  154.   // free up already used space
  155.   if (smival.value.string.ptr)
  156.   {
  157.     delete [] smival.value.string.ptr;
  158.     smival.value.string.ptr = 0;
  159.   }
  160.   smival.value.string.len = 0;
  161.   m_changed = true;
  162.   // check for zero len
  163.   if (!str || !len)
  164.   {
  165.     validity = true;
  166.     return;
  167.   }
  168.   // get the mem needed
  169.   smival.value.string.ptr = (SmiLPBYTE) new unsigned char[len];
  170.   if (smival.value.string.ptr)
  171.   {
  172.     MEMCPY(smival.value.string.ptr, str, len);
  173.     smival.value.string.len = len;
  174.     validity = true;
  175.   }
  176.   else
  177.     validity = false;
  178. }
  179. //=============[ assignment to a string operator overloaded ]=========
  180. OctetStr& OctetStr::operator=(const char *str)
  181. {
  182.   size_t nz;
  183.   // free up previous memory if needed
  184.   if (smival.value.string.ptr)
  185.   {
  186.     delete [] smival.value.string.ptr;
  187.     smival.value.string.ptr = 0;
  188.     smival.value.string.len = 0;
  189.   }
  190.   m_changed = true;
  191.   // if empty then we are done; get the string size
  192.   if (!str || !(nz = strlen(str)))
  193.   {
  194.     validity = true;
  195.     return *this;
  196.   }
  197.   // get memory needed
  198.   smival.value.string.ptr = (SmiLPBYTE) new unsigned char[nz];
  199.   if (smival.value.string.ptr)
  200.   {
  201.     MEMCPY(smival.value.string.ptr, str, nz);
  202.     smival.value.string.len = SAFE_INT_CAST(nz);
  203.     validity = true;
  204.   }
  205.   else
  206.     validity = false;
  207.   return *this;      // return self reference
  208. }
  209. //=============[ assignment to another oid object overloaded ]========
  210. OctetStr& OctetStr::operator=(const OctetStr &octet)
  211. {
  212.   if (this == &octet)  return *this; // protect against assignment from self
  213.   if (!octet.validity) return *this; // don't assign from invalid objs
  214.   set_data(octet.smival.value.string.ptr, octet.smival.value.string.len);
  215.   return *this;        // return self reference
  216. }
  217. //==============[ equivlence operator overloaded ]====================
  218. int operator==(const OctetStr &lhs, const OctetStr &rhs)
  219. {
  220.   if (lhs.smival.value.string.len != rhs.smival.value.string.len)
  221.     return false;
  222.   return (lhs.nCompare(rhs.smival.value.string.len, rhs) == 0);
  223. }
  224. //==============[ not equivlence operator overloaded ]================
  225. int operator!=(const OctetStr &lhs, const OctetStr &rhs)
  226. {
  227.   if (lhs.smival.value.string.len != rhs.smival.value.string.len)
  228.     return true;
  229.   return (lhs.nCompare(rhs.smival.value.string.len, rhs) != 0);
  230. }
  231. //==============[ less than < overloaded ]============================
  232. int operator<(const OctetStr &lhs, const OctetStr &rhs)
  233. {
  234.   int maxlen = lhs.smival.value.string.len > rhs.smival.value.string.len
  235.              ? lhs.smival.value.string.len : rhs.smival.value.string.len;
  236.   return (lhs.nCompare(maxlen, rhs) < 0);
  237. }
  238. //==============[ less than <= overloaded ]===========================
  239. int operator<=(const OctetStr &lhs, const OctetStr &rhs)
  240. {
  241.   int maxlen = lhs.smival.value.string.len > rhs.smival.value.string.len
  242.              ? lhs.smival.value.string.len : rhs.smival.value.string.len;
  243.   return (lhs.nCompare(maxlen, rhs) <= 0);
  244. }
  245. //===============[ greater than > overloaded ]========================
  246. int operator>(const OctetStr &lhs, const OctetStr &rhs)
  247. {
  248.   int maxlen = lhs.smival.value.string.len > rhs.smival.value.string.len
  249.              ? lhs.smival.value.string.len : rhs.smival.value.string.len;
  250.   return (lhs.nCompare(maxlen, rhs) > 0);
  251. }
  252. //===============[ greater than >= overloaded ]=======================
  253. int operator>=(const OctetStr &lhs, const OctetStr &rhs)
  254. {
  255.   int maxlen = lhs.smival.value.string.len > rhs.smival.value.string.len
  256.              ? lhs.smival.value.string.len : rhs.smival.value.string.len;
  257.   return (lhs.nCompare(maxlen, rhs) >=0);
  258. }
  259. //===============[ equivlence operator overloaded ]===================
  260. int operator==(const OctetStr &lhs, const char *rhs)
  261. {
  262.   OctetStr to(rhs);
  263.   if (lhs.smival.value.string.len != to.smival.value.string.len)
  264.     return false;
  265.   return (lhs.nCompare(to.smival.value.string.len, to) == 0);
  266. }
  267. //===============[ not equivlence operator overloaded ]===============
  268. int operator!=(const OctetStr &lhs, const char *rhs)
  269. {
  270.   OctetStr to(rhs);
  271.   if (lhs.smival.value.string.len != to.smival.value.string.len)
  272.     return true;
  273.   return (lhs.nCompare(to.smival.value.string.len, to) != 0);
  274. }
  275. //===============[ less than < operator overloaded ]==================
  276. int operator<(const OctetStr &lhs, const char *rhs)
  277. {
  278.   OctetStr to(rhs);
  279.   int maxlen = lhs.smival.value.string.len > to.smival.value.string.len
  280.              ? lhs.smival.value.string.len : to.smival.value.string.len;
  281.   return (lhs.nCompare(maxlen,to) < 0);
  282. }
  283. //===============[ less than <= operator overloaded ]=================
  284. int operator<=(const OctetStr &lhs, const char *rhs)
  285. {
  286.   OctetStr to(rhs);
  287.   int maxlen = lhs.smival.value.string.len > to.smival.value.string.len
  288.              ? lhs.smival.value.string.len : to.smival.value.string.len;
  289.   return (lhs.nCompare(maxlen, to) <= 0);
  290. }
  291. //===============[ greater than > operator overloaded ]===============
  292. int operator>(const OctetStr &lhs, const char *rhs)
  293. {
  294.   OctetStr to(rhs);
  295.   int maxlen = lhs.smival.value.string.len > to.smival.value.string.len
  296.              ? lhs.smival.value.string.len : to.smival.value.string.len;
  297.   return (lhs.nCompare(maxlen, to) > 0);
  298. }
  299. //===============[ greater than >= operator overloaded ]==============
  300. int operator>=(const OctetStr &lhs, const char *rhs)
  301. {
  302.   OctetStr to(rhs);
  303.   int maxlen = lhs.smival.value.string.len > to.smival.value.string.len
  304.              ? lhs.smival.value.string.len : to.smival.value.string.len;
  305.   return (lhs.nCompare(maxlen, to) >= 0);
  306. }
  307. //===============[ append operator, appends a string ]================
  308. OctetStr& OctetStr::operator+=(const char *a)
  309. {
  310.   unsigned char *tmp;
  311.   size_t slen, nlen;
  312.   // get len of string
  313.   if (!a || ((slen = strlen(a)) == 0))
  314.     return *this;
  315.   nlen = slen + (size_t) smival.value.string.len;  // total len of new octet
  316.   tmp = (SmiLPBYTE) new unsigned char[nlen];  // get mem needed
  317.   if (tmp)
  318.   {
  319.     // copy in the original 1st
  320.     MEMCPY(tmp, smival.value.string.ptr, smival.value.string.len);
  321.     // copy in the string
  322.     MEMCPY(tmp + smival.value.string.len, a, slen);
  323.     // delete the original
  324.     if (smival.value.string.ptr)
  325.       delete [] smival.value.string.ptr;
  326.     // point to the new one
  327.     smival.value.string.ptr = tmp;
  328.     smival.value.string.len = SAFE_INT_CAST(nlen);
  329.     m_changed = true;
  330.   }
  331.   return *this;
  332. }
  333. //================[ append one OctetStr to another ]==================
  334. OctetStr& OctetStr::operator+=(const OctetStr& octet)
  335. {
  336.   unsigned char *tmp;
  337.   size_t slen, nlen;
  338.   if (!octet.validity || !(slen = (size_t)octet.len()))
  339.     return *this;
  340.   nlen = slen + (size_t) smival.value.string.len;  // total len of new octet
  341.   tmp = (SmiLPBYTE) new unsigned char[nlen];  // get mem needed
  342.   if (tmp)
  343.   {
  344.     // copy in the original 1st
  345.     MEMCPY(tmp, smival.value.string.ptr, smival.value.string.len);
  346.     // copy in the string
  347.     MEMCPY(tmp + smival.value.string.len, octet.data(), slen);
  348.     // delete the original
  349.     if (smival.value.string.ptr )
  350.       delete [] smival.value.string.ptr;
  351.     // point to the new one
  352.     smival.value.string.ptr = tmp;
  353.     smival.value.string.len = SAFE_INT_CAST(nlen);
  354.     m_changed = true;
  355.   }
  356.   return *this;
  357. }
  358. //================[ appends a char ]==================================
  359. OctetStr& OctetStr::operator+=(const unsigned char c)
  360. {
  361.   unsigned char *tmp;
  362.   // get the memory needed plus one extra byte
  363.   tmp = (SmiLPBYTE) new unsigned char[smival.value.string.len + 1];
  364.   if (tmp)
  365.   {
  366.     MEMCPY(tmp, smival.value.string.ptr, smival.value.string.len);
  367.     tmp[smival.value.string.len] = c;  // assign in new byte
  368.     if (smival.value.string.ptr) // delete the original
  369.       delete [] smival.value.string.ptr;
  370.     smival.value.string.ptr = tmp; // point to new one
  371.     smival.value.string.len++;     // up the len
  372.     m_changed = true;
  373.   }
  374.   return *this;       // return self reference
  375. }
  376. //================[ compare n elements of an Octet ]==================
  377. int OctetStr::nCompare(const unsigned long n, const OctetStr &o) const
  378. {
  379.   unsigned long n_max;
  380.   unsigned long w,str_len;
  381.   if (n == 0) return 0; // Nothing to compare, strings are equal
  382.   // both are empty, they are equal
  383.   if ((smival.value.string.len == 0) && (o.smival.value.string.len == 0))
  384.     return 0;  // equal
  385.   // self is empty and param has something
  386.   if ((smival.value.string.len == 0) && (o.smival.value.string.len > 0))
  387.     return -1;
  388.   // self has something and param has nothing
  389.   if ((smival.value.string.len > 0) && (o.smival.value.string.len == 0))
  390.     return 1;
  391.   // now: n > 0; this.len > 0; o.len > 0 !!!
  392.   // pick the Min of n, this and the param len
  393.   // this is the maximum # to iterate a search
  394.   str_len = smival.value.string.len < o.smival.value.string.len
  395.     ? smival.value.string.len : o.smival.value.string.len;
  396.   w = (n <= str_len) ? n : str_len;
  397.   unsigned long z = 0;
  398.   while (z < w)
  399.   {
  400.     if (smival.value.string.ptr[z] < o.smival.value.string.ptr[z])
  401.       return -1; // less than
  402.     if (smival.value.string.ptr[z] > o.smival.value.string.ptr[z])
  403.       return 1; // greater than
  404.     z++;
  405.   }
  406.   // now: z == w > 0
  407.   // set n_max to min(n, max(len of strings))
  408.   n_max = smival.value.string.len > o.smival.value.string.len
  409.           ? smival.value.string.len : o.smival.value.string.len;
  410.   if (n< n_max) n_max = n;
  411.   if (w < n_max) // ==> we have compared too few bytes
  412.   {
  413.     if (smival.value.string.len < o.smival.value.string.len)
  414.       return -1;
  415.     else
  416.       return 1;
  417.   }
  418.   return 0;
  419. }
  420. //================[ ASCII format return ]=============================
  421. const char *OctetStr::get_printable() const
  422. {
  423.   if ((m_changed == false) &&
  424.       (output_last_function == OutputFunctionDefault))
  425.     return output_buffer;
  426.   for (unsigned long i=0; i < smival.value.string.len; i++)
  427.   {
  428.     if ((smival.value.string.ptr[i] != 'r')&&
  429. (smival.value.string.ptr[i] != 'n')&&
  430. (isprint((int) (smival.value.string.ptr[i]))==0))
  431.       switch (hex_output_type)
  432.       {
  433.         case OutputClear:        return get_printable_clear();
  434.         case OutputHexAndClear:
  435.         case OutputHex:
  436.         default:                 return get_printable_hex();
  437.       }
  438.   }
  439.   OctetStr *ncthis = PP_CONST_CAST(OctetStr*, this);
  440.   if (output_buffer_len < smival.value.string.len + 1)
  441.   {
  442.     if (output_buffer) delete [] ncthis->output_buffer;
  443.     ncthis->output_buffer = new char[smival.value.string.len + 1];
  444.     if (ncthis->output_buffer)
  445.       ncthis->output_buffer_len = smival.value.string.len + 1;
  446.   }
  447.   if (smival.value.string.len)
  448.     MEMCPY(ncthis->output_buffer,
  449.    smival.value.string.ptr, (unsigned int) smival.value.string.len);
  450.   ncthis->output_buffer[smival.value.string.len] = '';
  451.   ncthis->m_changed = false;
  452.   ncthis->output_last_function = OutputFunctionDefault;
  453.   return output_buffer;
  454. }
  455. //================[ ASCII format return ]=============================
  456. const char *OctetStr::get_printable_clear() const
  457. {
  458.   if ((m_changed == false) &&
  459.       (output_last_np_char == nonprintable_char) &&
  460.       (output_last_function == OutputFunctionClear))
  461.     return output_buffer;
  462.   OctetStr *ncthis = PP_CONST_CAST(OctetStr*, this);
  463.   if (output_buffer_len < smival.value.string.len + 1)
  464.   {
  465.     if (output_buffer) delete [] ncthis->output_buffer;
  466.     ncthis->output_buffer = new char[smival.value.string.len + 1];
  467.     if (ncthis->output_buffer)
  468.       ncthis->output_buffer_len = smival.value.string.len + 1;
  469.   }
  470.   if (smival.value.string.len)
  471.   {
  472.     for (unsigned long i=0; i < smival.value.string.len; i++)
  473.     {
  474.       if (isprint((int) (smival.value.string.ptr[i]))==0)
  475.         ncthis->output_buffer[i] = nonprintable_char;
  476.       else
  477.         ncthis->output_buffer[i] = smival.value.string.ptr[i];
  478.     }
  479.   }
  480.   ncthis->output_buffer[smival.value.string.len] = '';
  481.   ncthis->output_last_np_char = nonprintable_char;
  482.   ncthis->m_changed = false;
  483.   ncthis->output_last_function = OutputFunctionClear;
  484.   return output_buffer;
  485. }
  486. //================[ general Value = operator ]========================
  487. SnmpSyntax& OctetStr::operator=(const SnmpSyntax &val)
  488. {
  489.   if (this == &val) return *this;  // protect against assignment from self
  490.   // blow away the old value
  491.   if (smival.value.string.ptr)
  492.   {
  493.     delete [] smival.value.string.ptr;
  494.     smival.value.string.ptr = 0;
  495.   }
  496.   smival.value.string.len = 0;
  497.   validity = false;
  498.   if (val.valid()){
  499.     switch (val.get_syntax()){
  500.       case sNMP_SYNTAX_OPAQUE:
  501.       case sNMP_SYNTAX_BITS:
  502.       case sNMP_SYNTAX_OCTETS:
  503.       case sNMP_SYNTAX_IPADDR:
  504. set_data(((OctetStr &)val).smival.value.string.ptr,
  505.  ((OctetStr &)val).smival.value.string.len);
  506. break;
  507.     }
  508.   }
  509.   m_changed = true;
  510.   return *this;
  511. }
  512. #define ATOI(x)  if      ((x >= 48) && (x <= 57)) x = x-48; /* 0-9 */ 
  513.                  else if ((x >= 65) && (x <= 70)) x = x-55; /* A-F */ 
  514.  else if ((x >= 97) && (x <=102)) x = x-87; /* a-f */ 
  515.          else x = 0
  516. //=======[ create an octet string from a hex string ]===================
  517. OctetStr OctetStr::from_hex_string(const OctetStr &hex_string)
  518. {
  519.   OctetStr val;
  520.   unsigned int p = 0;
  521.   unsigned int hex_len = 0;
  522.   // make sure the string has at least one byte
  523.   if (hex_string.len() == 0) return val;
  524.   // allocate max needed space for copy without spaces
  525.   unsigned char *hex, *hex_ptr;
  526.   hex = hex_ptr = new unsigned char[hex_string.len()];
  527.   if (!hex) return val;
  528.   // delete spaces
  529.   const unsigned char *ptr = hex_string.smival.value.string.ptr;
  530.   for (p = hex_string.len(); p > 0; p--)
  531.   {
  532.     unsigned char c = *ptr++;
  533.     if (c != ' ')
  534.     {
  535.       *hex_ptr++ = c;
  536.       ++hex_len;
  537.     }
  538.   }
  539.   // leading 0 may be omitted
  540.   if (hex_len % 2)
  541.   {
  542.     unsigned char c = hex[0];
  543.     ATOI(c);
  544.     val += c;
  545.     p = 1;
  546.   }
  547.   else
  548.   {
  549.     p = 0;
  550.   }
  551.   while (p < hex_len)
  552.   {
  553.     unsigned char c = hex[p++];
  554.     unsigned char d = hex[p++];
  555.     ATOI(c);
  556.     ATOI(d);
  557.     val += (c*16 + d);
  558.   }
  559.   delete[] hex;
  560.   return val;
  561. }
  562. #undef ATOI
  563. //================[ format the output into hex ]========================
  564. const char *OctetStr::get_printable_hex() const
  565. {
  566.   if ((m_changed == false) && (output_last_type == hex_output_type) &&
  567.       (output_last_np_char == nonprintable_char) &&
  568.       (output_last_function == OutputFunctionHex))
  569.     return output_buffer;
  570.   int cnt;
  571.   char char_buf[80];              // holds ASCII representation of data
  572.   char *buf_ptr;                  // pointer into ASCII listing
  573.   char *line_ptr;                 // pointer into Hex listing
  574.   unsigned int  storageNeeded;    // how much space do we need ?
  575.   int  local_len = (int) smival.value.string.len;
  576.   unsigned char *bytes = smival.value.string.ptr;
  577.   storageNeeded = (unsigned int) ((smival.value.string.len/16)+1) * 72 + 1;
  578.   OctetStr *ncthis = PP_CONST_CAST(OctetStr*, this);
  579.   if (output_buffer_len < storageNeeded)
  580.   {
  581.     if (output_buffer)  delete [] ncthis->output_buffer;
  582.     ncthis->output_buffer = new char[storageNeeded];
  583.     if (ncthis->output_buffer)
  584.       ncthis->output_buffer_len = storageNeeded;
  585.   }
  586.   line_ptr = ncthis->output_buffer;
  587.   /*----------------------------------------*/
  588.   /* processing loop for entire data buffer */
  589.   /*----------------------------------------*/
  590.   while (local_len > 0)
  591.   {
  592.     cnt      = 16;   /* print 16 bytes per line */
  593.     buf_ptr  = char_buf;
  594.     sprintf(line_ptr, "  ");
  595.     line_ptr += 2;  /* indent */
  596.     /*-----------------------*/
  597.     /* process a single line */
  598.     /*-----------------------*/
  599.     while (cnt-- > 0 && local_len-- > 0)
  600.     {
  601.       sprintf(line_ptr, "%2.2X ", *bytes);
  602.       line_ptr +=3;   /* the display of a byte always 3 chars long */
  603.       if (isprint(*bytes))
  604. *buf_ptr++ = *bytes;
  605.       else
  606. *buf_ptr++ = nonprintable_char;
  607.       ++bytes;
  608.     }
  609.     ++cnt;
  610.     *buf_ptr = 0; // null terminate string
  611.     /*----------------------------------------------------------*/
  612.     /* this is to make sure that the ASCII displays line up for */
  613.     /* incomplete lines of hex                                  */
  614.     /*----------------------------------------------------------*/
  615.     while (cnt-- > 0)
  616.     {
  617.       *line_ptr++ = ' ';
  618.       *line_ptr++ = ' ';
  619.       *line_ptr++ = ' ';
  620.     }
  621.     /*------------------------------------------*/
  622.     /* append the ASCII display to the Hex line */
  623.     /*------------------------------------------*/
  624.     if (hex_output_type == OutputHex)
  625.       char_buf[0] = 0;
  626.     sprintf(line_ptr,"   %s%s", char_buf, linefeed_chars);
  627.     line_ptr += 3 + strlen(char_buf) + strlen(linefeed_chars);
  628.   }
  629.   ncthis->output_last_type = hex_output_type;
  630.   ncthis->output_last_np_char = nonprintable_char;
  631.   ncthis->m_changed = false;
  632.   ncthis->output_last_function = OutputFunctionHex;
  633.   return output_buffer;
  634. }
  635. //==============[ Null out the contents of the string ]===================
  636. void OctetStr::clear()
  637. {
  638.   if (smival.value.string.len > 0)
  639.   {
  640.     memset(smival.value.string.ptr, 0, smival.value.string.len);
  641.     smival.value.string.len = 0;
  642.   }
  643.   if (output_buffer)
  644.     memset(output_buffer, 0, output_buffer_len);
  645.   m_changed = true;
  646. }
  647. //============[Return the space needed for serialization]=================
  648. int OctetStr::get_asn1_length() const
  649. {
  650.   if (smival.value.string.len < 0x80)
  651.     return smival.value.string.len + 2;
  652.   else if (smival.value.string.len < 0x100)
  653.     return smival.value.string.len + 3;
  654.   else if (smival.value.string.len < 0x10000)
  655.     return smival.value.string.len + 4;
  656.   else if (smival.value.string.len < 0x1000000)
  657.     return smival.value.string.len + 5;
  658.   return smival.value.string.len + 6; // should be safe for some time...
  659. }
  660. //========[Set the character for linefeeds in get_printable() functions]====
  661. bool OctetStr::set_linefeed_chars(const char* lf_chars)
  662. {
  663.     if (!lf_chars) return false;
  664.     if (strlen(lf_chars) > 2) return false;
  665.     linefeed_chars[2] = 0;
  666.     linefeed_chars[1] = lf_chars[1];
  667.     linefeed_chars[0] = lf_chars[0];
  668.     return true;
  669. }
  670. //===============[ append or shorten the data buffer ]================
  671. bool OctetStr::set_len(const unsigned char new_len)
  672. {
  673.   unsigned char *tmp;
  674.   if (new_len <= smival.value.string.len)
  675.   {
  676.     smival.value.string.len = new_len;
  677.     m_changed = true;
  678.     if (new_len == 0)
  679.     {
  680.       if (smival.value.string.ptr) delete [] smival.value.string.ptr;
  681.       smival.value.string.ptr = 0;
  682.     }
  683.     return true;
  684.   }
  685.   tmp = (SmiLPBYTE) new unsigned char[new_len];  // get mem needed
  686.   if (!tmp) return false;
  687.   if (smival.value.string.ptr)
  688.     MEMCPY(tmp, smival.value.string.ptr, smival.value.string.len);
  689.   memset(tmp + smival.value.string.len, 0, new_len - smival.value.string.len);
  690.   if (smival.value.string.ptr)
  691.     delete [] smival.value.string.ptr;
  692.   smival.value.string.ptr = tmp;
  693.   smival.value.string.len = new_len;
  694.   m_changed = true;
  695.   return true;
  696. }
  697. #ifdef SNMP_PP_NAMESPACE
  698. }; // end of namespace Snmp_pp
  699. #endif