2015-05-03 19:32:37 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 11:12:37 +00:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2006-03-31 08:41:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* A class which represents a fragment of text (eg inside a text
|
|
|
|
* node); if only codepoints below 256 are used, the text is stored as
|
2014-01-04 15:02:17 +00:00
|
|
|
* a char*; otherwise the text is stored as a char16_t*
|
2006-03-31 08:41:49 +00:00
|
|
|
*/
|
|
|
|
|
1998-10-20 00:17:17 +00:00
|
|
|
#ifndef nsTextFragment_h___
|
|
|
|
#define nsTextFragment_h___
|
|
|
|
|
2011-11-21 06:21:16 +00:00
|
|
|
#include "mozilla/Attributes.h"
|
2013-06-23 12:03:39 +00:00
|
|
|
#include "mozilla/MemoryReporting.h"
|
2011-11-21 06:21:16 +00:00
|
|
|
|
2010-07-30 22:55:42 +00:00
|
|
|
#include "nsString.h"
|
2011-04-14 20:58:36 +00:00
|
|
|
#include "nsReadableUtils.h"
|
2014-02-26 21:36:35 +00:00
|
|
|
#include "nsISupportsImpl.h"
|
2011-07-19 17:04:09 +00:00
|
|
|
|
2001-03-08 02:41:16 +00:00
|
|
|
class nsString;
|
1998-10-20 00:17:17 +00:00
|
|
|
|
|
|
|
// XXX should this normalize the code to keep a \u0000 at the end?
|
|
|
|
|
|
|
|
// XXX nsTextFragmentPool?
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A fragment of text. If mIs2b is 1 then the m2b pointer is valid
|
|
|
|
* otherwise the m1b pointer is valid. If m1b is used then each byte
|
|
|
|
* of data represents a single ucs2 character with the high byte being
|
|
|
|
* zero.
|
|
|
|
*
|
|
|
|
* This class does not have a virtual destructor therefore it is not
|
|
|
|
* meant to be subclassed.
|
|
|
|
*/
|
2015-03-21 16:28:04 +00:00
|
|
|
class nsTextFragment final {
|
1998-10-20 00:17:17 +00:00
|
|
|
public:
|
2006-03-24 03:29:52 +00:00
|
|
|
static nsresult Init();
|
|
|
|
static void Shutdown();
|
|
|
|
|
1998-10-20 00:17:17 +00:00
|
|
|
/**
|
|
|
|
* Default constructor. Initialize the fragment to be empty.
|
|
|
|
*/
|
2008-02-02 23:41:24 +00:00
|
|
|
nsTextFragment()
|
2012-07-30 14:20:58 +00:00
|
|
|
: m1b(nullptr), mAllBits(0)
|
2008-02-02 23:41:24 +00:00
|
|
|
{
|
2009-03-08 19:01:02 +00:00
|
|
|
MOZ_COUNT_CTOR(nsTextFragment);
|
2008-02-02 23:41:24 +00:00
|
|
|
NS_ASSERTION(sizeof(FragmentBits) == 4, "Bad field packing!");
|
|
|
|
}
|
1998-10-20 00:17:17 +00:00
|
|
|
|
2001-03-08 02:41:16 +00:00
|
|
|
~nsTextFragment();
|
1998-10-20 00:17:17 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Change the contents of this fragment to be a copy of the
|
2013-12-19 14:09:00 +00:00
|
|
|
* the argument fragment, or to "" if unable to allocate enough memory.
|
1998-10-20 00:17:17 +00:00
|
|
|
*/
|
|
|
|
nsTextFragment& operator=(const nsTextFragment& aOther);
|
|
|
|
|
|
|
|
/**
|
2014-01-04 15:02:17 +00:00
|
|
|
* Return true if this fragment is represented by char16_t data
|
1998-10-20 00:17:17 +00:00
|
|
|
*/
|
2011-09-29 06:19:26 +00:00
|
|
|
bool Is2b() const
|
2001-12-10 09:46:33 +00:00
|
|
|
{
|
1999-09-22 00:38:57 +00:00
|
|
|
return mState.mIs2b;
|
1998-10-20 00:17:17 +00:00
|
|
|
}
|
|
|
|
|
2001-12-12 04:28:25 +00:00
|
|
|
/**
|
2011-10-17 14:59:28 +00:00
|
|
|
* Return true if this fragment contains Bidi text
|
2011-09-09 16:27:00 +00:00
|
|
|
* For performance reasons this flag is only set if explicitely requested (by
|
|
|
|
* setting the aUpdateBidi argument on SetTo or Append to true).
|
2001-12-12 04:28:25 +00:00
|
|
|
*/
|
2011-09-29 06:19:26 +00:00
|
|
|
bool IsBidi() const
|
2001-12-12 04:28:25 +00:00
|
|
|
{
|
|
|
|
return mState.mIsBidi;
|
|
|
|
}
|
|
|
|
|
1998-10-20 00:17:17 +00:00
|
|
|
/**
|
2014-01-04 15:02:17 +00:00
|
|
|
* Get a pointer to constant char16_t data.
|
1998-10-20 00:17:17 +00:00
|
|
|
*/
|
2014-01-04 15:02:17 +00:00
|
|
|
const char16_t *Get2b() const
|
2001-12-10 09:46:33 +00:00
|
|
|
{
|
1998-10-20 00:17:17 +00:00
|
|
|
NS_ASSERTION(Is2b(), "not 2b text");
|
|
|
|
return m2b;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a pointer to constant char data.
|
|
|
|
*/
|
2001-12-10 09:46:33 +00:00
|
|
|
const char *Get1b() const
|
|
|
|
{
|
1998-10-20 00:17:17 +00:00
|
|
|
NS_ASSERTION(!Is2b(), "not 1b text");
|
2001-12-10 09:46:33 +00:00
|
|
|
return (const char *)m1b;
|
1998-10-20 00:17:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the length of the fragment. The length is the number of logical
|
|
|
|
* characters, not the number of bytes to store the characters.
|
|
|
|
*/
|
2012-08-22 15:56:38 +00:00
|
|
|
uint32_t GetLength() const
|
2001-12-10 09:46:33 +00:00
|
|
|
{
|
2006-10-28 01:22:53 +00:00
|
|
|
return mState.mLength;
|
1998-10-20 00:17:17 +00:00
|
|
|
}
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool CanGrowBy(size_t n) const
|
2010-04-09 22:55:11 +00:00
|
|
|
{
|
|
|
|
return n < (1 << 29) && mState.mLength + n < (1 << 29);
|
|
|
|
}
|
|
|
|
|
1998-10-20 00:17:17 +00:00
|
|
|
/**
|
|
|
|
* Change the contents of this fragment to be a copy of the given
|
2011-09-09 16:27:00 +00:00
|
|
|
* buffer. If aUpdateBidi is true, contents of the fragment will be scanned,
|
|
|
|
* and mState.mIsBidi will be turned on if it includes any Bidi characters.
|
1998-10-20 00:17:17 +00:00
|
|
|
*/
|
2014-01-04 15:02:17 +00:00
|
|
|
bool SetTo(const char16_t* aBuffer, int32_t aLength, bool aUpdateBidi);
|
1998-10-20 00:17:17 +00:00
|
|
|
|
|
|
|
/**
|
2011-09-09 16:27:00 +00:00
|
|
|
* Append aData to the end of this fragment. If aUpdateBidi is true, contents
|
|
|
|
* of the fragment will be scanned, and mState.mIsBidi will be turned on if
|
|
|
|
* it includes any Bidi characters.
|
1998-10-20 00:17:17 +00:00
|
|
|
*/
|
2014-01-04 15:02:17 +00:00
|
|
|
bool Append(const char16_t* aBuffer, uint32_t aLength, bool aUpdateBidi);
|
1998-10-20 00:17:17 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Append the contents of this string fragment to aString
|
|
|
|
*/
|
2010-07-30 22:55:42 +00:00
|
|
|
void AppendTo(nsAString& aString) const {
|
2015-01-28 09:00:40 +00:00
|
|
|
if (!AppendTo(aString, mozilla::fallible)) {
|
2014-11-12 08:13:44 +00:00
|
|
|
aString.AllocFailed(aString.Length() + GetLength());
|
2014-03-19 17:05:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Append the contents of this string fragment to aString
|
|
|
|
* @return false if an out of memory condition is detected, true otherwise
|
|
|
|
*/
|
2015-03-19 07:46:40 +00:00
|
|
|
MOZ_WARN_UNUSED_RESULT
|
2014-03-19 17:05:02 +00:00
|
|
|
bool AppendTo(nsAString& aString,
|
2015-03-19 07:46:40 +00:00
|
|
|
const mozilla::fallible_t& aFallible) const {
|
2010-07-30 22:55:42 +00:00
|
|
|
if (mState.mIs2b) {
|
2015-01-28 09:00:40 +00:00
|
|
|
bool ok = aString.Append(m2b, mState.mLength, aFallible);
|
2014-03-19 17:05:02 +00:00
|
|
|
if (!ok) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2010-07-30 22:55:42 +00:00
|
|
|
} else {
|
2014-03-19 17:05:02 +00:00
|
|
|
return AppendASCIItoUTF16(Substring(m1b, mState.mLength), aString,
|
2015-01-28 09:00:40 +00:00
|
|
|
aFallible);
|
2010-07-30 22:55:42 +00:00
|
|
|
}
|
|
|
|
}
|
1998-10-20 00:17:17 +00:00
|
|
|
|
2006-10-19 01:47:47 +00:00
|
|
|
/**
|
|
|
|
* Append a substring of the contents of this string fragment to aString.
|
|
|
|
* @param aOffset where to start the substring in this text fragment
|
|
|
|
* @param aLength the length of the substring
|
|
|
|
*/
|
2012-08-22 15:56:38 +00:00
|
|
|
void AppendTo(nsAString& aString, int32_t aOffset, int32_t aLength) const {
|
2015-01-28 09:00:40 +00:00
|
|
|
if (!AppendTo(aString, aOffset, aLength, mozilla::fallible)) {
|
2014-11-12 08:13:44 +00:00
|
|
|
aString.AllocFailed(aString.Length() + aLength);
|
2014-03-19 17:05:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Append a substring of the contents of this string fragment to aString.
|
|
|
|
* @param aString the string in which to append
|
|
|
|
* @param aOffset where to start the substring in this text fragment
|
|
|
|
* @param aLength the length of the substring
|
|
|
|
* @return false if an out of memory condition is detected, true otherwise
|
|
|
|
*/
|
2015-03-19 07:46:40 +00:00
|
|
|
MOZ_WARN_UNUSED_RESULT
|
2014-03-19 17:05:02 +00:00
|
|
|
bool AppendTo(nsAString& aString, int32_t aOffset, int32_t aLength,
|
2015-03-19 07:46:40 +00:00
|
|
|
const mozilla::fallible_t& aFallible) const
|
2014-03-19 17:05:02 +00:00
|
|
|
{
|
2010-07-30 22:55:42 +00:00
|
|
|
if (mState.mIs2b) {
|
2015-01-28 09:00:40 +00:00
|
|
|
bool ok = aString.Append(m2b + aOffset, aLength, aFallible);
|
2014-03-19 17:05:02 +00:00
|
|
|
if (!ok) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2010-07-30 22:55:42 +00:00
|
|
|
} else {
|
2014-03-19 17:05:02 +00:00
|
|
|
return AppendASCIItoUTF16(Substring(m1b + aOffset, aLength), aString,
|
2015-01-28 09:00:40 +00:00
|
|
|
aFallible);
|
2010-07-30 22:55:42 +00:00
|
|
|
}
|
|
|
|
}
|
2006-10-19 01:47:47 +00:00
|
|
|
|
1998-10-20 00:17:17 +00:00
|
|
|
/**
|
|
|
|
* Make a copy of the fragments contents starting at offset for
|
|
|
|
* count characters. The offset and count will be adjusted to
|
|
|
|
* lie within the fragments data. The fragments data is converted if
|
|
|
|
* necessary.
|
|
|
|
*/
|
2014-01-04 15:02:17 +00:00
|
|
|
void CopyTo(char16_t *aDest, int32_t aOffset, int32_t aCount);
|
1998-10-20 00:17:17 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the character in the text-fragment at the given
|
2014-01-04 15:02:17 +00:00
|
|
|
* index. This always returns a char16_t.
|
1998-10-20 00:17:17 +00:00
|
|
|
*/
|
2014-01-04 15:02:17 +00:00
|
|
|
char16_t CharAt(int32_t aIndex) const
|
2001-12-10 09:46:33 +00:00
|
|
|
{
|
2012-08-22 15:56:38 +00:00
|
|
|
NS_ASSERTION(uint32_t(aIndex) < mState.mLength, "bad index");
|
2007-07-08 07:08:04 +00:00
|
|
|
return mState.mIs2b ? m2b[aIndex] : static_cast<unsigned char>(m1b[aIndex]);
|
1998-10-20 00:17:17 +00:00
|
|
|
}
|
|
|
|
|
2001-12-10 15:43:18 +00:00
|
|
|
struct FragmentBits {
|
2012-08-22 15:56:38 +00:00
|
|
|
// uint32_t to ensure that the values are unsigned, because we
|
2007-03-28 03:57:36 +00:00
|
|
|
// want 0/1, not 0/-1!
|
2011-09-29 06:19:26 +00:00
|
|
|
// Making these bool causes Windows to not actually pack them,
|
2007-03-28 03:57:36 +00:00
|
|
|
// which causes crashes because we assume this structure is no more than
|
|
|
|
// 32 bits!
|
2012-08-22 15:56:38 +00:00
|
|
|
uint32_t mInHeap : 1;
|
|
|
|
uint32_t mIs2b : 1;
|
|
|
|
uint32_t mIsBidi : 1;
|
|
|
|
uint32_t mLength : 29;
|
2001-12-10 15:43:18 +00:00
|
|
|
};
|
|
|
|
|
2013-06-23 12:03:39 +00:00
|
|
|
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
2011-07-19 17:04:09 +00:00
|
|
|
|
2006-03-24 03:29:52 +00:00
|
|
|
private:
|
2001-12-10 09:46:33 +00:00
|
|
|
void ReleaseText();
|
1999-09-22 00:38:57 +00:00
|
|
|
|
2011-09-09 16:27:00 +00:00
|
|
|
/**
|
|
|
|
* Scan the contents of the fragment and turn on mState.mIsBidi if it
|
|
|
|
* includes any Bidi characters.
|
|
|
|
*/
|
2014-01-04 15:02:17 +00:00
|
|
|
void UpdateBidiFlag(const char16_t* aBuffer, uint32_t aLength);
|
2011-09-09 16:27:00 +00:00
|
|
|
|
2001-12-10 09:46:33 +00:00
|
|
|
union {
|
2014-01-04 15:02:17 +00:00
|
|
|
char16_t *m2b;
|
2006-03-24 03:29:52 +00:00
|
|
|
const char *m1b; // This is const since it can point to shared data
|
2001-12-10 09:46:33 +00:00
|
|
|
};
|
|
|
|
|
1999-09-22 00:38:57 +00:00
|
|
|
union {
|
2012-08-22 15:56:38 +00:00
|
|
|
uint32_t mAllBits;
|
2001-12-10 15:43:18 +00:00
|
|
|
FragmentBits mState;
|
1999-09-22 00:38:57 +00:00
|
|
|
};
|
1998-10-20 00:17:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* nsTextFragment_h___ */
|
1999-09-23 19:02:23 +00:00
|
|
|
|