add stringtokenizer and View::setTag

This commit is contained in:
houzh 2024-02-19 20:56:16 +08:00
parent f59305c5cf
commit 5e613ee23c
4 changed files with 275 additions and 4 deletions

View File

@ -0,0 +1,218 @@
#include <utils/stringtokenizer.h>
//#include <core/textutils.h>
namespace cdroid{
namespace Character{
static constexpr int MIN_HIGH_SURROGATE=0xD800;
static constexpr int MAX_LOW_SURROGATE =0xDBFF;
int charCount(int unicodeValue) {
// 单字节字符
if (unicodeValue >= 0 && unicodeValue <= 0x7F) {
return 1;
}// 双字节字符
else if (unicodeValue >= 0x80 && unicodeValue <= 0x7FF) {
return 2;
}// 三字节字符
else if (unicodeValue >= 0x800 && unicodeValue <= 0xFFFF) {
return 3;
}// 四字节字符
else if (unicodeValue >= 0x10000 && unicodeValue <= 0x10FFFF) {
return 4;
}// 非法的Unicode值
else {
return -1;
}
}
int codePointAt(const std::string&str,int i){
const uint8_t startByte = str.at(i);
int charLength = 0;
if((startByte&0xC0)!=0x80)return -1;
if ((startByte & 0x80) == 0) { // 单字节字符
charLength = 1;
} else if ((startByte & 0xE0) == 0xC0) { // 双字节字符
charLength = 2;
} else if ((startByte & 0xF0) == 0xE0) { // 三字节字符
charLength = 3;
} else if ((startByte & 0xF8) == 0xF0) { // 四字节字符
charLength = 4;
}
int codePoint = (str[i] & (0xFF >> charLength)) << (6 * (charLength - 1));
for (int j = 1; j < charLength; ++j) {
if (i+j < str.length()) {
codePoint |= (str[i+j] & 0x3F) << (6 * (charLength - 1 - j));
} else {
return -1; // 不完整的UTF-8编码
}
}
return -1;
}
}
void StringTokenizer::setMaxDelimCodePoint() {
if (mDelimiters.empty()) {
maxDelimCodePoint = 0;
return;
}
int m = 0;
int c;
int count = 0;
for (int i = 0; i < mDelimiters.length(); i += Character::charCount(c)) {
c = mDelimiters.at(i);
if (c >= Character::MIN_HIGH_SURROGATE && c <= Character::MAX_LOW_SURROGATE) {
c = Character::codePointAt(mDelimiters,i);//mDelimiters.codePointAt(i);
mHasSurrogates = true;
}
if (m < c)
m = c;
count++;
}
maxDelimCodePoint = m;
if (mHasSurrogates) {
mDelimiterCodePoints.resize(count);
for (int i = 0, j = 0; i < count; i++, j += Character::charCount(c)) {
c = Character::codePointAt(mDelimiters,j);//mDelimiters.codePointAt(j);
mDelimiterCodePoints[i] = c;
}
}
}
StringTokenizer::StringTokenizer(const std::string& str,const std::string& delim, bool returnDelims) {
mCurrentPosition = 0;
mNewPosition = -1;
mDelimsChanged = false;
mStr = str;
mDelimiters = delim;
mMaxPosition = mStr.length();
mRetDelims = returnDelims;
mHasSurrogates = false;
setMaxDelimCodePoint();
}
StringTokenizer::StringTokenizer(const std::string& str,const std::string& delim)
:StringTokenizer(str, delim, false){
}
StringTokenizer::StringTokenizer(const std::string& str)
:StringTokenizer(str, " \t\n\r\f", false){
}
int StringTokenizer::skipDelimiters(int startPos)const{
if (mDelimiters.empty())
throw "new NullPointerException()";
int position = startPos;
while (!mRetDelims && position < mMaxPosition) {
if (!mHasSurrogates) {
char c = mStr.at(position);
if ((c > maxDelimCodePoint) || (mDelimiters.find(c)!=std::string::npos))//indexOf(c) < 0))
break;
position++;
} else {
int c = Character::codePointAt(mStr,position);//mStr.codePointAt(position)
if ((c > maxDelimCodePoint) || !isDelimiter(c)) {
break;
}
position += Character::charCount(c);
}
}
return position;
}
int StringTokenizer::scanToken(int startPos)const{
int position = startPos;
while (position < mMaxPosition) {
if (!mHasSurrogates) {
char c = mStr.at(position);
if ((c <= maxDelimCodePoint) && (mDelimiters.find(c)>=0))//indexOf(c) >= 0))
break;
position++;
} else {
int c = Character::codePointAt(mStr,position);//mStr.codePointAt(position);
if ((c <= maxDelimCodePoint) && isDelimiter(c))
break;
position += Character::charCount(c);
}
}
if (mRetDelims && (startPos == position)) {
if (!mHasSurrogates) {
char c = mStr.at(position);//charAt(position);
if ((c <= maxDelimCodePoint) && (mDelimiters.find(c)>=0))//indexOf(c) >= 0))
position++;
} else {
int c = Character::codePointAt(mStr,position);//mStr.codePointAt(position);
if ((c <= maxDelimCodePoint) && isDelimiter(c))
position += Character::charCount(c);
}
}
return position;
}
bool StringTokenizer::isDelimiter(int codePoint)const{
for (int delimiterCodePoint : mDelimiterCodePoints) {
if (delimiterCodePoint == codePoint) {
return true;
}
}
return false;
}
bool StringTokenizer::hasMoreTokens(){
mNewPosition = skipDelimiters(mCurrentPosition);
return (mNewPosition < mMaxPosition);
}
std::string StringTokenizer::nextToken() {
mCurrentPosition = (mNewPosition >= 0 && !mDelimsChanged) ?
mNewPosition : skipDelimiters(mCurrentPosition);
/* Reset these anyway */
mDelimsChanged = false;
mNewPosition = -1;
if (mCurrentPosition >= mMaxPosition)
throw "new NoSuchElementException()";
const int start = mCurrentPosition;
mCurrentPosition = scanToken(mCurrentPosition);
return mStr.substr(start, mCurrentPosition);
}
std::string StringTokenizer::nextToken(const std::string& delim) {
mDelimiters = delim;
/* delimiter string specified, so set the appropriate flag. */
mDelimsChanged = true;
setMaxDelimCodePoint();
return nextToken();
}
bool StringTokenizer::hasMoreElements(){
return hasMoreTokens();
}
std::string StringTokenizer::nextElement() {
return nextToken();
}
int StringTokenizer::countTokens()const{
int count = 0;
int currpos = mCurrentPosition;
while (currpos < mMaxPosition) {
currpos = skipDelimiters(currpos);
if (currpos >= mMaxPosition)
break;
currpos = scanToken(currpos);
count++;
}
return count;
}
}

View File

@ -0,0 +1,35 @@
#ifndef __STRING_TOKENIZER_H__
#define __STRING_TOKENIZER_H__
#include <vector>
#include <string>
namespace cdroid{
class StringTokenizer{
private:
int mCurrentPosition;
int mNewPosition;
int mMaxPosition;
std::string mStr;
std::string mDelimiters;
bool mRetDelims;
bool mDelimsChanged;
int maxDelimCodePoint;
bool mHasSurrogates = false;
std::vector<int> mDelimiterCodePoints;
private:
void setMaxDelimCodePoint();
int skipDelimiters(int startPos)const;
int scanToken(int startPos)const;
bool isDelimiter(int codePoint)const;
public:
StringTokenizer(const std::string& str,const std::string& delim, bool returnDelims);
StringTokenizer(const std::string& str,const std::string& delim);
StringTokenizer(const std::string& str);
bool hasMoreTokens();
std::string nextToken();
std::string nextToken(const std::string& delim);
bool hasMoreElements();
std::string nextElement();
int countTokens()const;
};
}/*endof namespace*/
#endif/*__STRING_TOKENIZER_H__*/

View File

@ -307,6 +307,7 @@ void View::initView(){
mDrawingCacheBackgroundColor = 0;
mContext = nullptr;
mParent = nullptr;
mKeyedTags = nullptr;
mAttachInfo = nullptr;
mListenerInfo= nullptr;
mTooltipInfo = nullptr;
@ -391,6 +392,7 @@ View::~View(){
if(isAttachedToWindow())onDetachedFromWindow();
if(mBackground)mBackground->setCallback(nullptr);
delete mKeyedTags;
delete mForegroundInfo;
delete mPendingCheckForTap;
delete mPendingCheckForLongPress;
@ -3222,15 +3224,29 @@ void*View::getTag()const{
}
void View::setTag(int key,void*tag){
mTag = tag;
//FATAL_IF((key>>24)<2,"The key must be an application-specific resource id.";
setKeyedTag(key,tag);
}
void*View::getTag(int key)const{
void* View::getTag(int key)const{
if (mKeyedTags != nullptr)
return mKeyedTags->get(key);
return nullptr;
}
void View::setTagInternal(int key, void* tag) {
//FATAL_IF(((key >> 24) != 0x1,"The key must be a framework-specific resource id.";
setKeyedTag(key, tag);
}
void View::setKeyedTag(int key,void* tag){
if(mKeyedTags ==nullptr)
mKeyedTags = new SparseArray<void*>();
mKeyedTags->put(key,tag);
}
View& View::setHint(const std::string&hint){
mHint=hint;
mHint = hint;
invalidate(true);
return *this;
}

View File

@ -384,7 +384,7 @@ private:
View&operator=(const View&) = delete;
//Temporary values used to hold (x,y) coordinates when delegating from the
// two-arg performLongClick() method to the legacy no-arg version
void setKeyedTag(int key,void* tag);
void removeTapCallback();
void removeLongPressCallback();
void removePerformClickCallback();
@ -495,6 +495,7 @@ protected:
Context* mContext;
LayoutParams* mLayoutParams;
TransformationInfo* mTransformationInfo;
SparseArray<void*>* mKeyedTags;
Animation* mCurrentAnimation;
std::vector<int> mDrawableState;
@ -872,6 +873,7 @@ public:
void*getTag()const;
void setTag(int key,void*tag);
void*getTag(int key)const;
void setTagInternal(int key, void* tag);
virtual View& setHint(const std::string&hint);
const std::string&getHint()const;
void setContentDescription(const std::string&);