text: //
  // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
  // Copyright (C) 2012-2013 LunarG, Inc.
  //
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions
  // are met:
  //
  //    Redistributions of source code must retain the above copyright
  //    notice, this list of conditions and the following disclaimer.
  //
  //    Redistributions in binary form must reproduce the above
  //    copyright notice, this list of conditions and the following
  //    disclaimer in the documentation and/or other materials provided
  //    with the distribution.
  //
  //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
  //    contributors may be used to endorse or promote products derived
  //    from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  // POSSIBILITY OF SUCH DAMAGE.
  //
  
  #ifndef _COMMON_INCLUDED_
  #define _COMMON_INCLUDED_
  
  
  #if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700)
  #include <sstream>
  namespace std {
  template<typename T>
  std::string to_string(const T& val) {
    std::ostringstream os;
    os << val;
    return os.str();
  }
  }
  #endif
  
  // -- GODOT start --
  #if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) /* || defined MINGW_HAS_SECURE_API*/
  // -- GODOT end --
      #include <basetsd.h>
      #ifndef snprintf
      #define snprintf sprintf_s
      #endif
      #define safe_vsprintf(buf,max,format,args) vsnprintf_s((buf), (max), (max), (format), (args))
  #elif defined (solaris)
      #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args))
      #include <sys/int_types.h>
      #define UINT_PTR uintptr_t
  #else
      #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args))
      #include <stdint.h>
      #define UINT_PTR uintptr_t
  #endif
  
  #if defined(_MSC_VER) && _MSC_VER < 1800
      #include <stdlib.h>
      inline long long int strtoll (const char* str, char** endptr, int base)
      {
          return _strtoi64(str, endptr, base);
      }
      inline unsigned long long int strtoull (const char* str, char** endptr, int base)
      {
          return _strtoui64(str, endptr, base);
      }
      inline long long int atoll (const char* str)
      {
          return strtoll(str, NULL, 10);
      }
  #endif
  
  #if defined(_MSC_VER)
  #define strdup _strdup
  #endif
  
  /* windows only pragma */
  #ifdef _MSC_VER
      #pragma warning(disable : 4786) // Don't warn about too long identifiers
      #pragma warning(disable : 4514) // unused inline method
      #pragma warning(disable : 4201) // nameless union
  #endif
  
  #include <set>
  #include <unordered_set>
  #include <vector>
  #include <map>
  #include <unordered_map>
  #include <list>
  #include <algorithm>
  #include <string>
  #include <cstdio>
  #include <cstdlib>
  #include <cassert>
  
  #include "PoolAlloc.h"
  
  //
  // Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
  //
  #define POOL_ALLOCATOR_NEW_DELETE(A)                                  \
      void* operator new(size_t s) { return (A).allocate(s); }          \
      void* operator new(size_t, void *_Where) { return (_Where); }     \
      void operator delete(void*) { }                                   \
      void operator delete(void *, void *) { }                          \
      void* operator new[](size_t s) { return (A).allocate(s); }        \
      void* operator new[](size_t, void *_Where) { return (_Where); }   \
      void operator delete[](void*) { }                                 \
      void operator delete[](void *, void *) { }
  
  namespace glslang {
  
      //
      // Pool version of string.
      //
      typedef pool_allocator<char> TStringAllocator;
      typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TString;
  
  } // end namespace glslang
  
  // Repackage the std::hash for use by unordered map/set with a TString key.
  namespace std {
  
      template<> struct hash<glslang::TString> {
          std::size_t operator()(const glslang::TString& s) const
          {
              const unsigned _FNV_offset_basis = 2166136261U;
              const unsigned _FNV_prime = 16777619U;
              unsigned _Val = _FNV_offset_basis;
              size_t _Count = s.size();
              const char* _First = s.c_str();
              for (size_t _Next = 0; _Next < _Count; ++_Next)
              {
                  _Val ^= (unsigned)_First[_Next];
                  _Val *= _FNV_prime;
              }
  
              return _Val;
          }
      };
  }
  
  namespace glslang {
  
  inline TString* NewPoolTString(const char* s)
  {
      void* memory = GetThreadPoolAllocator().allocate(sizeof(TString));
      return new(memory) TString(s);
  }
  
  template<class T> inline T* NewPoolObject(T*)
  {
      return new(GetThreadPoolAllocator().allocate(sizeof(T))) T;
  }
  
  template<class T> inline T* NewPoolObject(T, int instances)
  {
      return new(GetThreadPoolAllocator().allocate(instances * sizeof(T))) T[instances];
  }
  
  //
  // Pool allocator versions of vectors, lists, and maps
  //
  template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
  public:
      POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
  
      typedef typename std::vector<T, pool_allocator<T> >::size_type size_type;
      TVector() : std::vector<T, pool_allocator<T> >() {}
      TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {}
      TVector(size_type i) : std::vector<T, pool_allocator<T> >(i) {}
      TVector(size_type i, const T& val) : std::vector<T, pool_allocator<T> >(i, val) {}
  };
  
  template <class T> class TList  : public std::list<T, pool_allocator<T> > {
  };
  
  template <class K, class D, class CMP = std::less<K> >
  class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<K const, D> > > {
  };
  
  template <class K, class D, class HASH = std::hash<K>, class PRED = std::equal_to<K> >
  class TUnorderedMap : public std::unordered_map<K, D, HASH, PRED, pool_allocator<std::pair<K const, D> > > {
  };
  
  //
  // Persistent string memory.  Should only be used for strings that survive
  // across compiles/links.
  //
  typedef std::basic_string<char> TPersistString;
  
  //
  // templatized min and max functions.
  //
  template <class T> T Min(const T a, const T b) { return a < b ? a : b; }
  template <class T> T Max(const T a, const T b) { return a > b ? a : b; }
  
  //
  // Create a TString object from an integer.
  //
  #if defined _MSC_VER || defined MINGW_HAS_SECURE_API
  inline const TString String(const int i, const int base = 10)
  {
      char text[16];     // 32 bit ints are at most 10 digits in base 10
      _itoa_s(i, text, sizeof(text), base);
      return text;
  }
  #else
  inline const TString String(const int i, const int /*base*/ = 10)
  {
      char text[16];     // 32 bit ints are at most 10 digits in base 10
  
      // we assume base 10 for all cases
      snprintf(text, sizeof(text), "%d", i);
  
      return text;
  }
  #endif
  
  struct TSourceLoc {
      void init()
      {
          name = nullptr; string = 0; line = 0; column = 0;
      }
      void init(int stringNum) { init(); string = stringNum; }
      // Returns the name if it exists. Otherwise, returns the string number.
      std::string getStringNameOrNum(bool quoteStringName = true) const
      {
          if (name != nullptr) {
              TString qstr = quoteStringName ? ("\"" + *name + "\"") : *name;
              std::string ret_str(qstr.c_str());
              return ret_str;
          }
          return std::to_string((long long)string);
      }
      const char* getFilename() const
      {
          if (name == nullptr)
              return nullptr;
          return name->c_str();
      }
      const char* getFilenameStr() const { return name == nullptr ? "" : name->c_str(); }
      TString* name; // descriptive name for this string, when a textual name is available, otherwise nullptr
      int string;
      int line;
      int column;
  };
  
  class TPragmaTable : public TMap<TString, TString> {
  public:
      POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
  };
  
  const int MaxTokenLength = 1024;
  
  template <class T> bool IsPow2(T powerOf2)
  {
      if (powerOf2 <= 0)
          return false;
  
      return (powerOf2 & (powerOf2 - 1)) == 0;
  }
  
  // Round number up to a multiple of the given powerOf2, which is not
  // a power, just a number that must be a power of 2.
  template <class T> void RoundToPow2(T& number, int powerOf2)
  {
      assert(IsPow2(powerOf2));
      number = (number + powerOf2 - 1) & ~(powerOf2 - 1);
  }
  
  template <class T> bool IsMultipleOfPow2(T number, int powerOf2)
  {
      assert(IsPow2(powerOf2));
      return ! (number & (powerOf2 - 1));
  }
  
  } // end namespace glslang
  
  #endif // _COMMON_INCLUDED_
  