/*****************************************************************************/
// Copyright 2006-2020 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE:	Adobe permits you to use, modify, and distribute this file in
// accordance with the terms of the Adobe license agreement accompanying it.
/*****************************************************************************/

/** \file
 * Text string representation.
 */

/*****************************************************************************/

#ifndef __dng_string__
#define __dng_string__

/*****************************************************************************/

#include "dng_types.h"
#include "dng_memory.h"

#include <memory>
#include <string>
#include <unordered_set>

/*****************************************************************************/

typedef std::basic_string<char,
						  std::char_traits<char>,
						  dng_std_allocator<char>> dng_std_string;
						  
/*****************************************************************************/

class dng_string
	{
	
	private:
	
		// Strings are always stored using UTF-8 encoding. Shared pointers
		// are used to provide copy-on-write optimizations.	 Null strings
		// are always encoded as a null shared pointer (not pointer to a
		// null string).
		
		std::shared_ptr<const dng_std_string> fData;
		
	public:
	
		dng_string ();
		
		dng_string (const dng_string &s);
		
		dng_string (const char *s);
		
		dng_string & operator= (const dng_string &s);
		
		~dng_string ();
		
		const char * Get () const;
		
		bool IsASCII () const;
		
		void Set (const char *s);
	
		void Set_ASCII (const char *s);
		
		void Set_UTF8 (const char *s);
		
		uint32 Get_SystemEncoding (dng_memory_data &buffer) const;
		
		void Set_SystemEncoding (const char *s);
		
		bool ValidSystemEncoding () const;
		
		void Set_JIS_X208_1990 (const char *s);
				  
		static uint32 DecodeUTF8 (const char *&s,
								  uint32 maxBytes = 6,
								  bool *isValid = NULL);
								  
		static bool IsUTF8 (const char *s);
		
		void Set_UTF8_or_System (const char *s);

		uint32 Get_UTF16 (dng_memory_data &buffer) const;
		
		void Set_UTF16 (const uint16 *s);
		
		void Clear ();
		
		void Truncate (uint32 maxBytes);
		
		bool TrimTrailingBlanks ();
		
		bool TrimLeadingBlanks ();
		
		bool IsEmpty () const;
		
		bool NotEmpty () const
			{
			return !IsEmpty ();
			}
			
		uint32 Length () const;
		
		bool operator== (const dng_string &s) const;
		
		bool operator!= (const dng_string &s) const
			{
			return !(*this == s);
			}
			
		// A utility for doing case insensitive comparisons on strings...
		
		static bool Matches (const char *t,
							 const char *s,
							 bool case_sensitive = false);
							 
		// ...wrapped up for use with dng_string.

		bool Matches (const char *s,
					  bool case_sensitive = false) const;

		bool StartsWith (const char *s,
						 bool case_sensitive = false) const;
						 
		bool EndsWith (const char *s,
					   bool case_sensitive = false) const;
					   
		bool Contains (const char *s,
					   bool case_sensitive = false,
					   int32 *match_offset = NULL) const;
						 
		bool Replace (const char *old_string,
					  const char *new_string,
					  bool case_sensitive = true);
		
		void ReplaceChars (char oldChar,
						   char newChar);
		
		bool TrimLeading (const char *s,
						  bool case_sensitive = false);
						  
		void Append (const char *s);
		
		void SetUppercase ();
		
		void SetLowercase ();
		
		void SetLineEndings (char ending);
		
		void SetLineEndingsToNewLines ()
			{
			SetLineEndings ('\n');
			}
			
		void SetLineEndingsToReturns ()
			{
			SetLineEndings ('\r');
			}
			
		void StripLowASCII ();
		
		void ForceASCII ();
		
		int32 Compare (const dng_string &s,
					   bool digitsAsNumber = true) const;

		// A utility to convert fields of numbers into comma separated numbers.

		void NormalizeAsCommaSeparatedNumbers ();

	};
	
/*****************************************************************************/

class dng_string_hash
	{

	public:
		
		size_t operator () (const dng_string &s) const;
		
	};

/*****************************************************************************/

typedef std::unordered_set<dng_string,
						   dng_string_hash> dng_string_table;

/*****************************************************************************/

#endif	// __dng_string__
	
/*****************************************************************************/
