⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nsbufferhandle.h

📁 linux下的一款播放器
💻 H
字号:
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is Mozilla strings. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are * Copyright (C) 2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): *   Scott Collins <scc@mozilla.org> (original author) * *//* nsBufferHandle.h --- the collection of classes that describe the atomic hunks of strings */#ifndef nsBufferHandle_h___#define nsBufferHandle_h___#ifndef nsStringDefines_h___#include "nsStringDefines.h"#endif#include "prtypes.h"  // for |PRBool|#include "nsDebug.h"  // for |NS_ASSERTION|#include "nscore.h"  // for |PRUnichar|, |NS_REINTERPRET_CAST|#ifdef _MSC_VER  // VC++ erroneously warns about incompatible linkage in these templates  //  It's a lie, and it's bothersome.  This |#pragma| quiets the warning.#pragma warning( disable: 4251 )#endif  /*   * The classes in this file are collectively called `buffer handles'.   * All buffer handles begin with a pointer-tuple that delimits the   * useful content of a hunk of string.  A buffer handle that points to   * a sharable hunk of string data additionally has a field which   * multiplexes some flags and a reference count.   *   *   *  ns[Const]BufferHandle       nsSharedBufferHandle   *  +-----+-----+-----+-----+   +-----+-----+-----+-----+   *  | mDataStart            |   | mDataStart            |   *  +-----+-----+-----+-----+   +-----+-----+-----+-----+   *  | mDataEnd              |   | mDataEnd              |   *  +-----+-----+-----+-----+   +-----+-----+-----+-----+   *                              | mFlags                |   *                              +-----+-----+-----+-----+   *                              | mStorageLength        |   *                              +-----+-----+-----+-----+   *                              . mAllocator            .   *                              .........................   *   * Given only a |ns[Const]BufferHandle|, there is no legal way to tell   * if it is sharable.  In all cases, the data might immediately follow   * the handle in the same allocated block.  From the |mFlags| field,   * you can tell exactly what configuration of a handle you actually   * have.   *   * An |nsSharedBufferHandle| has the limitation that its |mDataStart|   * must also be the beginning of the allocated storage.  However,   * allowing otherwise would introduce significant additional   * complexity for a feature that would better be handled by allowing   * an owninng substring string class that owned a reference to the   * buffer handle.   */  /**   *   * @status FROZEN   */template <class CharT>class nsBufferHandle  {    public:      typedef PRUint32                          size_type;      nsBufferHandle() { }      nsBufferHandle( CharT* aDataStart, CharT* aDataEnd ) : mDataStart(aDataStart), mDataEnd(aDataEnd) { }      void          DataStart( CharT* aNewDataStart )       { mDataStart = aNewDataStart; }      CharT*        DataStart()                             { return mDataStart; }      const CharT*  DataStart() const                       { return mDataStart; }      void          DataEnd( CharT* aNewDataEnd )           { mDataEnd = aNewDataEnd; }      CharT*        DataEnd()                               { return mDataEnd; }      const CharT*  DataEnd() const                         { return mDataEnd; }      size_type     DataLength() const                      { return mDataEnd - mDataStart; }    protected:      CharT*  mDataStart;      CharT*  mDataEnd;  };  /**   *   * @status FROZEN   */template <class CharT>class nsConstBufferHandle  {    public:      typedef PRUint32                          size_type;      nsConstBufferHandle() { }      nsConstBufferHandle( const CharT* aDataStart, const CharT* aDataEnd ) : mDataStart(aDataStart), mDataEnd(aDataEnd) { }      void          DataStart( const CharT* aNewDataStart ) { mDataStart = aNewDataStart; }      const CharT*  DataStart() const                       { return mDataStart; }      void          DataEnd( const CharT* aNewDataEnd )     { mDataEnd = aNewDataEnd; }      const CharT*  DataEnd() const                         { return mDataEnd; }      size_type     DataLength() const                      { return mDataEnd - mDataStart; }    protected:      const CharT*  mDataStart;      const CharT*  mDataEnd;  };  /**   * string allocator stuff needs to move to its own file   * also see http://bugzilla.mozilla.org/show_bug.cgi?id=70087   */template <class CharT>class nsStringAllocator  {    public:      // more later      virtual void Deallocate( CharT* ) const = 0;  };  /**   * the following two routines must be provided by the client embedding strings   */NS_COM nsStringAllocator<char>&      StringAllocator_char();NS_COM nsStringAllocator<PRUnichar>& StringAllocator_wchar_t();  /**   * this traits class lets templated clients pick the appropriate non-template global allocator   */template <class T>struct nsStringAllocatorTraits  {  };NS_SPECIALIZE_TEMPLATEstruct nsStringAllocatorTraits<char>  {    static nsStringAllocator<char>&      global_string_allocator() { return StringAllocator_char(); }  };NS_SPECIALIZE_TEMPLATEstruct nsStringAllocatorTraits<PRUnichar>  {    static nsStringAllocator<PRUnichar>& global_string_allocator() { return StringAllocator_wchar_t(); }  };// end of string allocator stuff that needs to movetemplate <class CharT>class nsSharedBufferHandle    : public nsBufferHandle<CharT>  {    public:      typedef PRUint32                          size_type;      enum        {          kIsImmutable                    = 0x01000000, // if this is set, the buffer cannot be modified even if its refcount is 1          kIsSingleAllocationWithBuffer   = 0x02000000, // handle and buffer are one piece, no separate deallocation is possible for the buffer          kIsUserAllocator                = 0x04000000, // can't |delete|, call a hook instead            // the following flags are opaque to the string library itself          kIsNULL                         = 0x80000000, // the most common request of external clients is a scheme by which they can express `NULL'-ness          kImplementationFlagsMask        = 0xF0000000, // 4 bits for use by site-implementations, e.g., for `NULL'-ness          kFlagsMask                      = 0xFF000000,          kRefCountMask                   = 0x00FFFFFF        };    public:      nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd, size_type aStorageLength, PRBool isSingleAllocation )          : nsBufferHandle<CharT>(aDataStart, aDataEnd),            mFlags(0),            mStorageLength(aStorageLength)        {          if ( isSingleAllocation )            mFlags |= kIsSingleAllocationWithBuffer;        }      ~nsSharedBufferHandle();      void      AcquireReference() const        {          nsSharedBufferHandle<CharT>* mutable_this = NS_CONST_CAST(nsSharedBufferHandle<CharT>*, this);          mutable_this->set_refcount( get_refcount()+1 );        }      void ReleaseReference() const;      PRBool      IsReferenced() const        {          return get_refcount() != 0;        }      PRBool      IsMutable() const        {          // (get_refcount() == 1) && !(GetImplementationFlags() & kIsImmutable)          return (mFlags & (kRefCountMask | kIsImmutable) == 1);        }      void StorageLength( size_type aNewStorageLength )        {          mStorageLength = aNewStorageLength;        }      size_type      StorageLength() const        {          return mStorageLength;        }      PRUint32      GetImplementationFlags() const        {          return mFlags & kImplementationFlagsMask;        }      void      SetImplementationFlags( PRUint32 aNewFlags )        {          mFlags = (mFlags & ~kImplementationFlagsMask) | (aNewFlags & kImplementationFlagsMask);        }    protected:      PRUint32  mFlags;      size_type mStorageLength;      PRUint32      get_refcount() const        {          return mFlags & kRefCountMask;        }      PRUint32      set_refcount( PRUint32 aNewRefCount )        {          NS_ASSERTION(aNewRefCount <= kRefCountMask, "aNewRefCount <= kRefCountMask");          mFlags = (mFlags & kFlagsMask) | aNewRefCount;          return aNewRefCount;        }      nsStringAllocator<CharT>& get_allocator() const;  };template <class CharT>class nsSharedBufferHandleWithAllocator    : public nsSharedBufferHandle<CharT>  {    public:      // why is this needed again?      typedef PRUint32                          size_type;      nsSharedBufferHandleWithAllocator( CharT* aDataStart, CharT* aDataEnd, size_type aStorageLength, nsStringAllocator<CharT>& aAllocator )          : nsSharedBufferHandle<CharT>(aDataStart, aDataEnd,                                        aStorageLength, PR_FALSE),            mAllocator(aAllocator)        {          this->mFlags |= this->kIsUserAllocator;        }      nsStringAllocator<CharT>& get_allocator() const { return mAllocator; }    protected:      nsStringAllocator<CharT>& mAllocator;  };// Derive from this class to implement a |Destroy| method.template <class CharT>class nsSharedBufferHandleWithDestroy    : public nsSharedBufferHandle<CharT>  {    public:      // why is this needed again?      typedef PRUint32                          size_type;      nsSharedBufferHandleWithDestroy( CharT* aDataStart, CharT* aDataEnd, size_type aStorageLength)          : nsSharedBufferHandle<CharT>(aDataStart, aDataEnd,                                        aStorageLength, PR_FALSE)        {          this->mFlags |=              this->kIsUserAllocator | this->kIsSingleAllocationWithBuffer;        }      virtual void Destroy() = 0;      // This doesn't really need to be |virtual|, but it saves us from      // having to turn off gcc warnings that might be useful to      // someone.      virtual ~nsSharedBufferHandleWithDestroy() { }  };template <class CharT>class nsNonDestructingSharedBufferHandle    : public nsSharedBufferHandleWithDestroy<CharT>  {    public:      // why is this needed again?      typedef PRUint32                          size_type;      nsNonDestructingSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd, size_type aStorageLength)          : nsSharedBufferHandleWithDestroy<CharT>(aDataStart, aDataEnd,                                                   aStorageLength)        {        }      virtual void Destroy()        {          // Oops, threads raced to set the refcount.  Set the refcount          // back to 1.          this->set_refcount(1);        }  };template <class CharT>nsStringAllocator<CharT>&nsSharedBufferHandle<CharT>::get_allocator() const    // really don't want this to be |inline|  {    if ( mFlags & kIsUserAllocator )      {        return NS_REINTERPRET_CAST(const nsSharedBufferHandleWithAllocator<CharT>*, this)->get_allocator();      }    return nsStringAllocatorTraits<CharT>::global_string_allocator();  }template <class CharT>nsSharedBufferHandle<CharT>::~nsSharedBufferHandle()    // really don't want this to be |inline|  {    NS_ASSERTION(!IsReferenced(), "!IsReferenced()");    if ( !(mFlags & kIsSingleAllocationWithBuffer) )      {        CharT* string_storage = this->mDataStart;        get_allocator().Deallocate(string_storage);      }  }template <class CharT>voidnsSharedBufferHandle<CharT>::ReleaseReference() const  {    nsSharedBufferHandle<CharT>* mutable_this = NS_CONST_CAST(nsSharedBufferHandle<CharT>*, this);    if ( !mutable_this->set_refcount( get_refcount()-1 ) )      {        if ( ~mFlags & (kIsUserAllocator|kIsSingleAllocationWithBuffer) )          delete mutable_this;        else          // If |kIsUserAllocator| and |kIsSingleAllocationWithBuffer|,          // the handle is an |nsSharedBufferHandleWithDestroy<CharT>|,          // so call its |Destroy| method.          NS_STATIC_CAST(nsSharedBufferHandleWithDestroy<CharT>*,                         mutable_this)->Destroy();      }  }#endif // !defined(nsBufferHandle_h___)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -