CWBuffer.hxx
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:15k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. #ifndef CWBUFFER_HXX_
  2. #define CWBUFFER_HXX_
  3. /* ====================================================================
  4.  * The Vovida Software License, Version 1.0 
  5.  * 
  6.  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
  7.  * 
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in
  17.  *    the documentation and/or other materials provided with the
  18.  *    distribution.
  19.  * 
  20.  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
  21.  *    and "Vovida Open Communication Application Library (VOCAL)" must
  22.  *    not be used to endorse or promote products derived from this
  23.  *    software without prior written permission. For written
  24.  *    permission, please contact vocal@vovida.org.
  25.  *
  26.  * 4. Products derived from this software may not be called "VOCAL", nor
  27.  *    may "VOCAL" appear in their name, without prior written
  28.  *    permission of Vovida Networks, Inc.
  29.  * 
  30.  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  31.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  33.  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
  34.  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
  35.  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
  36.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  37.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  38.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  39.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  40.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  41.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  42.  * DAMAGE.
  43.  * 
  44.  * ====================================================================
  45.  * 
  46.  * This software consists of voluntary contributions made by Vovida
  47.  * Networks, Inc. and many individuals on behalf of Vovida Networks,
  48.  * Inc.  For more information on Vovida Networks, Inc., please see
  49.  * <http://www.vovida.org/>.
  50.  *
  51.  */
  52. static const char* const CWBuffer_hxx_Version =
  53.     "$Id: CWBuffer.hxx,v 1.15 2001/05/25 23:21:53 sprajpat Exp $";
  54. #include "CountSemaphore.hxx"
  55. #include <string.h>
  56. #include <ctype.h>
  57. #include "Sptr.hxx"
  58. #include "fastmemcpy.hxx"
  59. #include "Lock.hxx"
  60. #include <iostream>
  61. #define INLINE_ inline
  62. #define BUFFER_STATISTICS 0
  63. class CWCharArray;
  64. INLINE_ int
  65. mystrlen(const char* s)
  66. {
  67.     int i = 0;
  68.     while (*s++ != '')
  69.     {
  70.         i++;
  71.     }
  72.     return i;
  73. }
  74. #if 1
  75. INLINE_ void*
  76. mmemcpy(char* dest, const char* s, int len)
  77. {
  78.     char *d = dest;
  79.     while (len--)
  80.     {
  81.         *d++ = *s++;
  82.     }
  83.     return dest;
  84. }
  85. #else
  86. #define mmemcpy memcpy
  87. #endif
  88. static char* emptyStr = "";
  89. /** character array structure used for copy on write data.  Do not
  90.  * derive from this class */
  91. class CWCharArray
  92. {
  93.     public:
  94. /// construct an array of length len
  95. CWCharArray(int len);
  96. /// construct an array of size allocsize, copying len bytes from p
  97. CWCharArray(const char* p, int len, int allocsize);
  98. /// destructor
  99. ~CWCharArray();
  100. CountSemaphore mutex;
  101. char* ptr;
  102. };
  103. #if (BUFFER_STATISTICS)
  104. struct BufferStats
  105. {
  106.     public:
  107. BufferStats() : refCount(0), realCount(0)
  108. {
  109. }
  110. int refCount;
  111. int realCount;
  112. };
  113. class BufferStatistic
  114. {
  115.     public:
  116. static void add(int size, CWCharArray* ptr)
  117. {
  118.     create();
  119.     Vocal::Process::Lock lock_(instance->bufferMutex);
  120.     instance->buffer[ptr] = size;
  121.     if(instance->rawSizes.find(size) == instance->rawSizes.end())
  122.     {
  123. instance->rawSizes[size] = 1;
  124.     }
  125.     else
  126.     {
  127. instance->rawSizes[size]++;
  128.     }
  129. }
  130. static void remove(CWCharArray* ptr)
  131. {
  132.     create();
  133.     Vocal::Process::Lock lock_(instance->bufferMutex);
  134.     map <CWCharArray*, int>::iterator i = instance->buffer.find(ptr);
  135.     if(i != instance->buffer.end())
  136.     {
  137. instance->buffer.erase(i);
  138.     }
  139. }
  140. static void print(ostream& s)
  141. {
  142.     create();
  143.     Vocal::Process::Lock lock_(instance->bufferMutex);
  144.     s << "nttBuffer Reportnn";
  145.     map <CWCharArray*, int>::iterator i;
  146.     map <int, BufferStats> myStats;
  147.     map <int, BufferStats>::iterator j;
  148.     for(i = instance->buffer.begin(); i != instance->buffer.end(); ++i)
  149.     {
  150. j = myStats.find(i->second);
  151. if(j == myStats.end())
  152. {
  153.     BufferStats x;
  154.     x.refCount = (i->first)->mutex.getCount();
  155.     x.realCount = 1;
  156.     myStats[i->second] = x;
  157. }
  158. else
  159. {
  160.     j->second.refCount += (i->first)->mutex.getCount();
  161.     j->second.realCount ++;
  162. }
  163. #if 0
  164. s << i->first
  165.   << ":"
  166.   << i->second
  167.   << ":"
  168.   << (i->first)->mutex.getCount()
  169.   << "n";
  170. #endif
  171.     }
  172.     s << "current:nn";
  173.     for(j = myStats.begin(); j != myStats.end(); ++j)
  174.     {
  175. s << j->first
  176.   << ":"
  177.   << j->second.realCount
  178.   << ":"
  179.   << j->second.refCount
  180.   << "n";
  181.     }
  182.     s << "allocs:nn";
  183.     for(map <int, int>::iterator k = instance->rawSizes.begin();
  184. k != instance->rawSizes.end(); 
  185. ++k)
  186.     {
  187. s << k->first
  188.   << ":"
  189.   << k->second
  190.   << "n";
  191.     }
  192. }
  193.     protected:
  194. BufferStatistic()
  195.     : bufferMutex(),
  196.       buffer()
  197. {
  198. }
  199. static void create()
  200. {
  201.     if(!instance)
  202.     {
  203. instance = new BufferStatistic;
  204.     }
  205. }
  206. static BufferStatistic* instance;
  207. VMutex bufferMutex;
  208. map <CWCharArray*, int> buffer;
  209. map <int, int> rawSizes;
  210. };
  211. INLINE_
  212. void printBufferStatistics(ostream& s)
  213. {
  214.     BufferStatistic::print(s);    
  215. }
  216. #else
  217. INLINE_
  218. void printBufferStatistics(ostream& s)
  219. {
  220.     // do nothing
  221.     return;
  222. }
  223. #endif
  224. extern "C" {
  225. void dumpBufferStatistics();
  226. };
  227. INLINE_
  228. CWCharArray::CWCharArray(int length)
  229.         : mutex()
  230. {
  231.     ptr = new char[length];
  232. #if (BUFFER_STATISTICS)
  233.     BufferStatistic::add(length, this);
  234. #endif
  235. }
  236. INLINE_
  237. CWCharArray::CWCharArray(const char* p, int len, int allocsize)
  238.         : mutex()
  239. {
  240.     assert(allocsize >= len);
  241.     ptr = new char[allocsize];
  242.     mmemcpy(ptr, p, len);
  243. #if (BUFFER_STATISTICS)
  244.     BufferStatistic::add(len, this);
  245. #endif
  246. }
  247. INLINE_
  248. CWCharArray::~CWCharArray()
  249. {
  250.     assert(mutex.compare(0));
  251.     delete[] ptr;
  252. #if (BUFFER_STATISTICS)
  253.     BufferStatistic::remove(this);
  254. #endif
  255. }
  256. INLINE_ void decrementCA(CWCharArray* ptr)
  257. {
  258.     if (ptr)
  259.     {
  260.         if (ptr->mutex.compare(0))
  261.         {
  262.             delete (ptr);
  263.             ptr = 0;
  264.         }
  265.         else if (ptr->mutex.decrement())
  266.         {
  267.             delete (ptr);
  268.             ptr = 0;
  269.         }
  270.     }
  271. }
  272. /** copy on write buffer, used in conjunction with CopyOnWriteData.
  273.  * Do not derive from this class */
  274. class CWBuffer
  275. {
  276.     public:
  277. /// default constructor (constructs an empty buffer of length len)
  278. CWBuffer(int len = 0);
  279. /// construct a buffer of size hint, copying length bytes from p
  280. CWBuffer(const char* src, int length, int hint = 0);
  281. /// copy constructor
  282. CWBuffer(const CWBuffer& src);
  283. /// destructor
  284. ~CWBuffer();
  285. /// assignment operator
  286. const CWBuffer& operator=(const CWBuffer& src);
  287. // these functions don't make modifications to the underlying
  288. // buffer, so they ought to be cheap
  289. /// clear the string
  290. void clear();
  291. /** compare this buffer with a character array
  292.     @param str  character array to compare against
  293.     @param rightSize  size of array to compare against
  294. */
  295. int compare(const char* str, int rightSize) const;
  296. /** compare this buffer with a character array
  297.     @param str  character array to compare against
  298.     @param rightSize  size of array to compare against
  299. */
  300. int compareCstr(const char* str) const;
  301. /** compare this buffer with a character array case-insensitvely
  302.     @param str  character array to compare against
  303.     @param rightSize  size of array to compare against
  304. */
  305. int compareNoCase(const char* str, int rightSize) const;
  306. /** split the string into two.  This object becomes the front,
  307.     which has all the characters w/ positions < p, while ptr
  308.     has the positions >= p.  Note that this is special in that
  309.     it does NOT write to any of the string, so the underlying
  310.     buffer is never written.
  311.     @param p    number of bytes to split at.
  312.     @param ptr  returned buffer, containing the positions >= p
  313. */
  314. void split(int p, CWBuffer* ptr);
  315. /** truncate the current  buffer.
  316.     @param front   number of characters to remove from the beginning 
  317.                    of the string
  318.     @param back    number of characters to remove from the end 
  319.                    of the string
  320. */
  321. void truncate(int front, int back);
  322. /** truncate the current buffer.
  323.     @param first    the first character of the string to keep
  324.     @param last     the last character of the string to keep
  325. */
  326. void substr(int first, int last);
  327. // these functions (potentially) modify the underlying buffer, so
  328. // they are (potentially) expensive
  329. /** verify that the current string can be written to, up to
  330.     length-1 characters.
  331.     @param length   number of characters in bitsPtr which are writable.
  332. */
  333. void makeWritable(int length);
  334. /** convert this string into a C string (a NUL terminated one) */
  335. void makeCString();
  336. CWCharArray* bufPtr;
  337. char* bitsPtr;
  338. int size;
  339. int allocSpace;
  340. };
  341. INLINE_
  342. CWBuffer::CWBuffer(int length)
  343.         :
  344.         bufPtr(0),
  345.         bitsPtr(emptyStr),
  346.         size(0),
  347.         allocSpace(length)
  348. {
  349.     if (allocSpace)
  350.     {
  351.         bufPtr = new CWCharArray(allocSpace);
  352.         bufPtr->mutex.increment();
  353.         bitsPtr = bufPtr->ptr;
  354.     }
  355. }
  356. INLINE_
  357. CWBuffer::CWBuffer(const char* src, int length, int hint)
  358.         :
  359.         bufPtr(0),
  360.         bitsPtr(emptyStr),
  361.         size(length),
  362.         allocSpace(length)
  363. {
  364.     if (hint > length)
  365.     {
  366.         allocSpace = hint;
  367.     }
  368.     if (allocSpace)
  369.     {
  370.         bufPtr = new CWCharArray(src, length, allocSpace);
  371.         bufPtr->mutex.increment();
  372.         bitsPtr = bufPtr->ptr;
  373.     }
  374. }
  375. INLINE_
  376. CWBuffer::CWBuffer(const CWBuffer& src)
  377.         :
  378.         bufPtr(src.bufPtr),
  379.         bitsPtr(src.bitsPtr),
  380.         size(src.size),
  381.         allocSpace(src.allocSpace)
  382. {
  383.     if (bufPtr)
  384.     {
  385.         bufPtr->mutex.increment();
  386.     }
  387. }
  388. INLINE_ const CWBuffer&
  389. CWBuffer::operator=(const CWBuffer& src)
  390. {
  391.     bufPtr = src.bufPtr;
  392.     bitsPtr = src.bitsPtr;
  393.     size = src.size;
  394.     allocSpace = src.allocSpace;
  395.     if (bufPtr)
  396.     {
  397.         bufPtr->mutex.increment();
  398.     }
  399.     return *this;
  400. }
  401. INLINE_ void
  402. CWBuffer::clear()
  403. {
  404.     if (bufPtr)
  405.     {
  406.         decrementCA(bufPtr);
  407.     }
  408.     bitsPtr = emptyStr;
  409.     size = 0;
  410.     allocSpace = 0;
  411.     bufPtr = 0;
  412. }
  413. INLINE_
  414. CWBuffer::~CWBuffer()
  415. {
  416.     decrementCA(bufPtr);
  417. }
  418. INLINE_ int
  419. CWBuffer::compare(const char* str, int rightSize) const
  420. {
  421.     char* ptr = bitsPtr;
  422.     int leftSize = size;
  423.     while (leftSize && rightSize)
  424.     {
  425.         if (*ptr < *str)
  426.         {
  427.             return -1;
  428.         }
  429.         if (*ptr > *str)
  430.         {
  431.             return 1;
  432.         }
  433.         leftSize--;
  434.         rightSize--;
  435.         ptr++;
  436.         str++;
  437.     }
  438.     if (leftSize < rightSize)
  439.     {
  440.         return -1;
  441.     }
  442.     else if (leftSize > rightSize)
  443.     {
  444.         return 1;
  445.     }
  446.     else
  447.     {
  448.         return 0;
  449.     }
  450. }
  451. INLINE_ int
  452. CWBuffer::compareCstr(const char* str) const
  453. {
  454.     char* ptr = bitsPtr;
  455.     int leftSize = size;
  456.     while (leftSize && (*str != ''))
  457.     {
  458.         if (*ptr < *str)
  459.         {
  460.             return -1;
  461.         }
  462.         if (*ptr > *str)
  463.         {
  464.             return 1;
  465.         }
  466.         leftSize--;
  467.         ptr++;
  468.         str++;
  469.     }
  470.     if ((leftSize == 0) && (*str != ''))
  471.     {
  472.         return -1;
  473.     }
  474.     else if ((leftSize > 0) && (*str == ''))
  475.     {
  476.         return 1;
  477.     }
  478.     else
  479.     {
  480.         return 0;
  481.     }
  482. }
  483. INLINE_ int
  484. CWBuffer::compareNoCase(const char* str, int rightSize) const
  485. {
  486.     char* ptr = bitsPtr;
  487.     int leftSize = size;
  488.     while (leftSize && rightSize)
  489.     {
  490.         if (std::toupper(*ptr) < std::toupper(*str))
  491.         {
  492.             return -1;
  493.         }
  494.         if (std::toupper(*ptr) > std::toupper(*str))
  495.         {
  496.             return 1;
  497.         }
  498.         leftSize--;
  499.         rightSize--;
  500.         ptr++;
  501.         str++;
  502.     }
  503.     if (leftSize < rightSize)
  504.     {
  505.         return -1;
  506.     }
  507.     else if (leftSize > rightSize)
  508.     {
  509.         return 1;
  510.     }
  511.     else
  512.     {
  513.         return 0;
  514.     }
  515. }
  516. INLINE_ void
  517. CWBuffer::split(int p, CWBuffer* ptr)
  518. {
  519.     assert((p >= 0) && (p <= size));
  520.     if (p == size)
  521.     {
  522.         // do not actually split, but return an empty CWBuffer.  p ==
  523.         // size is a border case where we do nothing, and return an
  524.         // empty string, since nothing belongs in the second half of
  525.         // the split.
  526.         ptr->clear();
  527.     }
  528.     else
  529.     {
  530.         // do the split
  531.         *ptr = *this;
  532.         // correct the new ptr
  533.         ptr->bitsPtr = ptr->bitsPtr + p;
  534.         ptr->size = ptr->size - p;
  535.         ptr->allocSpace = ptr->allocSpace - p;
  536.         // correct the old ptr
  537.         allocSpace = p;
  538.         size = p;
  539.     }
  540. }
  541. INLINE_ void
  542. CWBuffer::truncate(int front, int back)
  543. {
  544.     assert((front + back) <= size);
  545.     bitsPtr = bitsPtr + front;
  546.     size = size - (front + back);
  547. }
  548. INLINE_ void
  549. CWBuffer::substr(int first, int last)
  550. {
  551.     assert((first <= last) &&
  552.            (first <= size) &&
  553.            (last <= size) &&
  554.            (first >= 0) &&
  555.            (last >= 0));
  556.     bitsPtr = bitsPtr + first;
  557.     size = (last - first);
  558. }
  559. INLINE_ void
  560. CWBuffer::makeWritable(int length)
  561. {
  562.     if (bufPtr)
  563.     {
  564.         if ( (length > allocSpace) || !bufPtr->mutex.compare(1))
  565.         {
  566.             // if we need more space than we have in this buffer, OR
  567.             // if this is not the only CWBuffer pointing to this
  568.             // CharArray, we need to copy it
  569. #if 0
  570.     // this is the policy
  571.             if (length > allocSpace)
  572.             {
  573.                 allocSpace = length + 128;
  574.             }
  575. #endif
  576.     // replace above policy with an exponential backoff
  577.     // policy.  See: http://www.gotw.ca/gotw/043.htm -- the
  578.     // comment is exponential increase of about 1.5 is best
  579.     // (allegedly from Andrew Koenig's column in the September
  580.     // 1998 issue of JOOP (Journal of Object-Oriented
  581.     // Programming).
  582.     if (length > allocSpace)
  583.     {
  584. allocSpace = length + length / 2;
  585.     }
  586.             CWCharArray* tmp = new CWCharArray(bitsPtr, size, allocSpace);
  587.             // this must be done first or it will cause problems
  588.             tmp->mutex.increment();
  589.             bitsPtr = tmp->ptr;
  590.     tmp->mutex.exchange(reinterpret_cast<void**>(&bufPtr), 
  591. reinterpret_cast<void**>(&tmp));
  592.             // get rid of the old pointer, now in tmp
  593.             decrementCA(tmp);
  594.         }
  595.     }
  596.     else if (length > 0)
  597.     {
  598.         assert(size == 0);
  599.         // allocate a buffer
  600. //        allocSpace = length + 128;
  601. // see above for the rationale for this
  602. allocSpace = length + length / 2;
  603.         bufPtr = new CWCharArray(allocSpace);
  604.         bitsPtr = bufPtr->ptr;
  605.         bufPtr->mutex.increment();
  606.     }
  607. }
  608. INLINE_ void
  609. CWBuffer::makeCString()
  610. {
  611.     if (bitsPtr != emptyStr)
  612.     {
  613.         makeWritable(size + 1);
  614.         bitsPtr[size] = '';
  615.     }
  616. }
  617. /* Local Variables: */
  618. /* c-file-style: "stroustrup" */
  619. /* indent-tabs-mode: nil */
  620. /* c-file-offsets: ((access-label . -) (inclass . ++)) */
  621. /* c-basic-offset: 4 */
  622. /* End: */
  623. #endif