DuiLib 源码分析之CDuiString
duilib是一个比较常见的界面库,闲来无事看看别人写的代码,跟自己写的一比,
才看到了差距呀,感觉自己写的乱七八糟,keep moving
CduiString是duilib提供的一个字符串类,功能是够用的,做duilib项目可以直接拿来用
首先看看头文件定义:
class UILIB_API CDuiString
{
public:
enum { MAX_LOCAL_STRING_LEN = }; CDuiString();
CDuiString(const TCHAR ch);
CDuiString(const CDuiString& src);
CDuiString(LPCTSTR lpsz, int nLen = -);
~CDuiString(); void Empty();
int GetLength() const;
bool IsEmpty() const;
TCHAR GetAt(int nIndex) const;
void Append(LPCTSTR pstr);
void Assign(LPCTSTR pstr, int nLength = -);
LPCTSTR GetData() const; void SetAt(int nIndex, TCHAR ch);
operator LPCTSTR() const; TCHAR operator[] (int nIndex) const;
const CDuiString& operator=(const CDuiString& src);
const CDuiString& operator=(const TCHAR ch);
const CDuiString& operator=(LPCTSTR pstr);
#ifdef _UNICODE
const CDuiString& CDuiString::operator=(LPCSTR lpStr);
const CDuiString& CDuiString::operator+=(LPCSTR lpStr);
#else
const CDuiString& CDuiString::operator=(LPCWSTR lpwStr);
const CDuiString& CDuiString::operator+=(LPCWSTR lpwStr);
#endif
CDuiString operator+(const CDuiString& src) const;
CDuiString operator+(LPCTSTR pstr) const;
const CDuiString& operator+=(const CDuiString& src);
const CDuiString& operator+=(LPCTSTR pstr);
const CDuiString& operator+=(const TCHAR ch); bool operator == (LPCTSTR str) const;
bool operator != (LPCTSTR str) const;
bool operator <= (LPCTSTR str) const;
bool operator < (LPCTSTR str) const;
bool operator >= (LPCTSTR str) const;
bool operator > (LPCTSTR str) const; int Compare(LPCTSTR pstr) const;
int CompareNoCase(LPCTSTR pstr) const; void MakeUpper();
void MakeLower(); CDuiString Left(int nLength) const;
CDuiString Mid(int iPos, int nLength = -) const;
CDuiString Right(int nLength) const; int Find(TCHAR ch, int iPos = ) const;
int Find(LPCTSTR pstr, int iPos = ) const;
int ReverseFind(TCHAR ch) const;
int Replace(LPCTSTR pstrFrom, LPCTSTR pstrTo); int __cdecl Format(LPCTSTR pstrFormat, ...);
int __cdecl SmallFormat(LPCTSTR pstrFormat, ...); protected:
LPTSTR m_pstr;//指向缓冲区的指针,可能指向m_szBuffer,也可能指向别的缓冲区
TCHAR m_szBuffer[MAX_LOCAL_STRING_LEN + ];//储存字符串的字符数组
};
看了定义之后其中的api大部分都会使用了吧
下面抓几个重要的函数来分析一下吧.
void CDuiString::Append(LPCTSTR pstr)
{
int nNewLength = GetLength() + (int) _tcslen(pstr);
if( nNewLength >= MAX_LOCAL_STRING_LEN ) {
if( m_pstr == m_szBuffer ) {
m_pstr = static_cast<LPTSTR>(malloc((nNewLength + ) * sizeof(TCHAR)));
_tcscpy(m_pstr, m_szBuffer);
_tcscat(m_pstr, pstr);
}
else {
m_pstr = static_cast<LPTSTR>(realloc(m_pstr, (nNewLength + ) * sizeof(TCHAR)));
_tcscat(m_pstr, pstr);
}
}
else {
if( m_pstr != m_szBuffer ) {//防止m_pstr指向别的地方
free(m_pstr);
m_pstr = m_szBuffer;
}
_tcscat(m_szBuffer, pstr);
}
}
Append函数用于在末尾添加字符串,首先判断添加后的的字符串长度是否比默认数组中能储存的长。1.超过了:先判断当前指针是否指向m_szBuffer,是的话则新申请一段内存,将原有的内容复制过去,再加上新增的即可,否的话先释放m_pstr中的内存再复制内容,新增。(注意这里realloc函数会在申请内存给m_pstr后将原有内容复制过去,并且释放原来m_pstr的内存)2.没有超过则直接添加即可
void CDuiString::Assign(LPCTSTR pstr, int cchMax)
{
if( pstr == NULL ) pstr = _T("");
cchMax = (cchMax < ? (int) _tcslen(pstr) : cchMax);
if( cchMax < MAX_LOCAL_STRING_LEN ) {
if( m_pstr != m_szBuffer ) {
free(m_pstr);
m_pstr = m_szBuffer;
}
}
else if( cchMax > GetLength() || m_pstr == m_szBuffer ) {
if( m_pstr == m_szBuffer ) m_pstr = NULL;//若指向m_szBuffer,不能将其释放,先指向NULL
m_pstr = static_cast<LPTSTR>(realloc(m_pstr, (cchMax + ) * sizeof(TCHAR)));
}
_tcsncpy(m_pstr, pstr, cchMax);
m_pstr[cchMax] = _T('\0');
}
Assign这个函数设计的十分精妙,很多地方都用到,它主要用于重新赋值操作。cchMax表示截取pstr的范围[0,cchMax),若m_szBuffer长度足以存储,则直接赋值,把指针指过去;若不够长,重新申请内存赋值
int CDuiString::Replace(LPCTSTR pstrFrom, LPCTSTR pstrTo)
{
CDuiString sTemp;
int nCount = ;
int iPos = Find(pstrFrom);
if( iPos < ) return ;
int cchFrom = (int) _tcslen(pstrFrom);
int cchTo = (int) _tcslen(pstrTo);
while( iPos >= ) {
sTemp = Left(iPos);
sTemp += pstrTo;
sTemp += Mid(iPos + cchFrom);
Assign(sTemp);
iPos = Find(pstrFrom, iPos + cchTo);
nCount++;
}
return nCount;
}
替换字符串,首先查找是否存在需要替换的字符串,没有则直接返回0,存在的话,将其分为三段,中间一段替换,用sTemp储存,再重新赋值sTemp,如此往复替换所有的pstrFrom。
int CDuiString::Format(LPCTSTR pstrFormat, ...)
{
LPTSTR szSprintf = NULL;
va_list argList;
int nLen;
va_start(argList, pstrFormat);
nLen = ::_vsntprintf(NULL, , pstrFormat, argList);
szSprintf = (TCHAR*)malloc((nLen + ) * sizeof(TCHAR));
ZeroMemory(szSprintf, (nLen + ) * sizeof(TCHAR));
int iRet = ::_vsntprintf(szSprintf, nLen + , pstrFormat, argList);
va_end(argList);
Assign(szSprintf);
free(szSprintf);
return iRet;
}
Format函数用于格式化字符串,与常用的printf类似。具体实现来看看,va_list argList, 这个是什么东东,一开始确实没见过,看看其定义
typedef char * va_list;原来是char*,它是用于指向可变参数的,va_start(argList,pstrFormat)后,argList指向第一个可变参数,接下来调用_vsntprintf(NULL,0,pstrFormat,argList),最后将格式化后的字符串重新赋值回去即可。
想了解关于va_list 可参考这里:http://blog.csdn.net/edonlii/article/details/8497704
其实难点也并非很难,只是一些需要注意的小问题总是会被自己忽略,看别人写的好的代码还是挺有收获的。
DuiLib 源码分析之CDuiString的更多相关文章
- Duilib源码分析(六)整体流程
在<Duilib源码分析(一)整体框架>.<Duilib源码分析(二)控件构造器—CDialogBuilder>以及<Duilib源码分析(三)XML解析器—CMarku ...
- Duilib源码分析(一)整体框架
Duilib界面库是一款由杭州月牙儿网络技术有限公司开发的界面开源库,以viksoe项目下的UiLib库的基础上开发(此后也将对UiLib库进行源码分析):通过XML布局界面,将用户界面和处理逻辑彻底 ...
- Duilib源码分析(三)XML解析器—CMarkup
上一节介绍了控件构造器CDialogBuilder,接下来将分析其XML解析器CMarkup: CMarkup:xml解析器,目前内置支持三种编码格式:UTF8.UNICODE.ASNI,默认为UTF ...
- Duilib源码分析(四)绘制管理器—CPaintManagerUI—(前期准备一)
上节中提到在遍历创建控件树后,执行了以下操作: 1. CDialogBuilder构建各控件对象并形成控件树,并返回第一个控件对象pRoot: 2. m_pm.AttachDialo ...
- Duilib源码分析(五)UI布局—Layout与各子控件
接下来,继续分析duilib之UI布局Layout,目前提供的布局有:VerticalLayout.HorizontalLayout.TileLayout.TabLayout.ChildLayout分 ...
- Duilib源码分析(四)绘制管理器—CPaintManagerUI
接下来,分析uilib.h中的UIManager.h,在正式分析CPaintManagerUI前先了解前面的一些宏.结构: 枚举类型EVENTTYPE_UI:定义了UIManager.h中事件通告类型 ...
- Duilib源码分析(四)绘制管理器—CPaintManagerUI—(前期准备三)
接下来,我们将继续分析UIlib.h文件中其他的文件, UIContainer.h, UIRender.h, WinImplBase.h, UIManager.h,以及其他布局.控件等: 1. UIR ...
- Duilib源码分析(四)绘制管理器—CPaintManagerUI—(前期准备二)
接下来,我们继续分析UIlib.h文件中余下的文件,当然部分文件可能顺序错开分析,这样便于从简单到复杂的整个过程的里面,而避免一开始就出现各种不理解的地方. 1. UIManager.h:UI管理器, ...
- Duilib源码分析(四)绘制管理器—CPaintManagerUI—(前期准备四)
接下来,分析uilib.h中的WinImplBase.h和UIManager.h: WinImplBase.h:窗口实现基类,已实现大部分的工作,基本上窗口类均可直接继承该类,可发现该类继承于多个类, ...
随机推荐
- 虚拟机下CentOS 6.5配置IP地址的三种方法
实验软件环境:虚拟机Vmware Workstation10.0 .CentOS 6.5 32位 1.自动获取IP地址 虚拟机使用桥接模式,相当于连接到物理机的网络里,物理机网络有DHCP服务器自动分 ...
- python numpy包
在numpy包中我们可以用数组来表示向量,矩阵和高阶数据结构 首先导入numpy包: from numpy import* 初始化numpy数组有多种方式,比如说 1.python列表或元祖 2.使用 ...
- jQuery Scroll Follow
Overview Scroll Follow is a simple jQuery plugin that enables a DOM object to follow the page as the ...
- 引用iScroll.js实现上拉和下拖刷新
使用技巧 1.引用iScroll.js, 在初始化时添加两个事件监听:touchMove.DOMContentLoaded. 2.实现iScroll插件的onScrollEnd事件, 也就是在这个事件 ...
- [Asp.net]Uploadify上传大文件,Http error 404 解决方案
引言 之前使用Uploadify做了一个上传图片并预览的功能,今天在项目中,要使用该插件上传大文件.之前弄过上传图片的demo,就使用该demo进行测试.可以查看我的这篇文章:[Asp.net]Upl ...
- Excel应该这么玩——7、我是预言家:绘制趋势图
让我们先看一个场景:你是公司销售部的员工,你手里有公司最近几年的销售额相关的数据,经理希望你预测下个月的销售额.盯着一堆数据,你或许会想到画一张XY坐标图,然后将每个月份的销售额标定为一个坐标.但是下 ...
- 基于MDK的mbed工程建立
个人更喜欢mdk作为IDE来编写代码,而mbed作为一个开源项目,有大量优秀代码可以借鉴使用,今后一段时间都会主要看mbed平台的代码以及国内ebox平台代码 1 首先登陆mbed在 ...
- [liusy.api-SMJ]-MAVEN archetype 创建项目
•选择或创建工作空间 Select a workspace –File – Switch Workspace - other
- css3基础必回选择器全解
1. *:通用元素选择器 * { margin: 0; padding: 0; } *选择器是选择页面上的全部元素,上面的代码作用是把全部元素的margin和padding设为0,最基本的清除 ...
- 相机拍的图,电脑上画的图,word里的文字,电脑屏幕,手机屏幕,相机屏幕显示大小一切的一切都搞明白了!
相机拍的图,电脑上画的图,word里的文字,电脑屏幕,手机屏幕,相机屏幕显示大小一切的一切都搞明白了! 先说图片X×dpi=点数dotX是图片实际尺寸,简单点,我们只算图片的高吧,比如说拍了张图片14 ...