KitCore的组成部分之一 ----- MSCore
MSCore
我对它的定义是Memory service, 即向上提供内存服务。
对外接口如下:
MSKIT_API MSERR MSAlloc(void** addPtr,unsigned long size);
MSKIT_API MSERR MSFree(void** addPtr);
MSKIT_API MSERR MSWrite(char** pAddress,char* CBWrite,unsigned long & offset,size_t writeLen,unsigned long* originalLen);
MSKIT_API MSERR MSRead(char* handle,char** CBRead,unsigned long & offset,size_t readLen);
MSKIT_API MSERR MSFRead(char* handle,char* CBRead,unsigned long & offset,size_t readLen);
MSKIT_API MSERR MSAutoSwapPointer(void** swapPtrA,void** swapPtrB);
MSKIT_API MSERR MSAutoSwspAndFree(void** outPtr,void** freePtr);
MSKIT_API 为标准的导入导出宏定义,MSERR即为MSCore内的错误码。
首先看到的是MSAlloc, 如你所见,所有的MSCore下的函数均以MS开头表明所属,后面使用功能来命名,如Alloc即申请内存,Free释放内存等。
实例代码如下:
BWI(iRet = MSAlloc((void**)&CBTypeE,iLen));
CBTypeE为char*类型,并被初始化为nil(即为NULL,必须被初始化为nil,否则会失败),iLen为申请长度,返回RC_SUCCESS即为成功(kitCore内部所有错误码均统一,即但凡成功均返回RC_SUCCESS)
当成功返回时,CBTypeE即被指向了长度为iLen的内存区,当需要释放资源时,
MSFree((void**)&CBTypeE);
我们并不关心MSFree的返回值,因为内部的排错机制会拒绝对非法的addPtr进行操作,等同于什么都没有发生,如果是合法的地址,则一定能够被释放,用户不需要关心。在成功释放内存时,CBTypeE即被自动重置为nil。
MSWrite的参数表稍具复杂度,首参为写入的目标地址空间,类同于MSAlloc的调用,使用char**作为引导,因此用户不需要关心写入缓冲区大小的问题,内部会自动拉长缓冲长度如果不够写的话,第二个参数即为写入的内容所在的目标地址空间,第三个作为如果多次写入(多次调用MSWrite写同一个pAddress)的其实偏移,第一次调用offset = 0,第四个参数为待写入的内容长度,第五个参数为当前的总长度。
代码样例可以去RCCore中的RCKit.core.cpp中1872行起始的函数(此时kitCore版本为2.3 inside)// 只有在2012.5.31后得到代码的童鞋才是这行。
RCKIT_API RCERR RmlWriteHead(char* RmlFilePath,RML_NODE_HEAD* head)
内部存在着大量的MSWrite调用。
MSRead 功能和MSWrite相对存在,可是参数表不同,第一个为待读取的缓冲起始地址,第二个为可变长缓冲区,使用方式和MSWrite类似,第三个是当前读取的偏移量,为多次读取提供控制,第一次必须为0,第四个参数为读取长度,长度超过待读取的缓冲区会失败。
MSFRead即为快速版本,XXFXX这种命名是为该函数的快速版本,抛弃可变长,即认为缓冲区必然足够长,函数内部不会抛出有效内存,需要外接提供可写的地址,其余参数不变。
后两个函数作为保留,不做解释 =。=
如果不清楚什么的 可以提出来,我会根据实际提供不同的更新。
update:
what is the BWI?
here it is.
#ifndef RCKit_macro_defaultx_h
#define RCKit_macro_defaultx_h
#define nil NULL
#define NO false
#define YES true
#ifdef RCKIT_ENV_SPEED
#define BWI(rcerr) if((RC_SUCCESS != rcerr)) break
#else
#define BWI(rcerr) if((RC_SUCCESS != (rcerr))) break
#endif
#define RCM(obj,rcerr,retA,retB) BWI((rcerr) = ((obj)?(retA):(retB)))
#define RCMP(__pointer,rcerr) RCM(__pointer,rcerr,RC_SUCCESS,RC_MSERR_MEMBER_NIL)
#define RCPP(__ptr_pointer,rcerr) RCM(__ptr_pointer,rcerr,RC_SUCCESS,RC_MSERR_MEMBER_NNIL)
#ifndef min(a,b)
#define min(a,b) ((a)>(b) ? (b):(a))
#endif
#ifndef max(a,b)
#define max(a,b) ((a)>(b) ? (a):(b))
#endif
#ifndef _DEBUG
#define KX_NO_IO
#endif
#ifndef KX_NO_IO
#define KX_IO_START
#endif
#ifdef KX_IO_START
#ifdef _WIN32
#include <Windows.h>
#endif
#include <iostream>
#define KCP(X) std::cout<<X<<std::endl;
#define KRP(X,Y) if((Y)) std::cout<<X<<std::endl; else std::cout<<X;
#define RPT(X,Y) printf(X,Y);
#define KDP(X,Y) if((Y)) std::cout<<X<<std::endl; else std::cout<<X; //debug version io test
#define POT(X,Y) printf(X,Y);
#define CST(X) KDP("Build the ",0);KDP(X,0);KDP(" in ",0);KDP(X,0);KDP("Class",1); //construction start
#define DST(X) KDP("Free the ",0);KDP(X,0);KDP(" in ",0);KDP(X,0);KDP("Class",1); //destruction start
#define CCST(X) KDP("Copy the ",0);KDP(X,0);KDP(" in ",0);KDP(X,0);KDP("Class",1); //copy construction start
#define SIC(X,Y) KDP(X,0);KDP(" in ",0);KDP(Y,0);KDP("Class",1); //start in class
//defined in the runtime library.and now move to here
#else
#ifdef _WIN32
#include <Windows.h>
#endif
#include <iostream>
#define KCP(X) std::cout<<X<<std::endl;
#define KRP(X,Y) if((Y)) std::cout<<X<<std::endl; else std::cout<<X;
#define KRP_TIME() std::cout<<GetLocalTime();
#define RPT(X,Y) printf(X,Y);
#define KDP(X,Y)
#define POT(X,Y)
#define CST(X)
#define DST(X)
#define CCST(X)
#define SIC(X,Y)
#endif
#endif
all the main code of a function is in the do{}while(0); block. and the default success code is zero, so once the problem happened , BWI will jump over automatically with the error code.
for instance:
IOKIT_API IOERR IOGetFileNameByFullName(char* fullName,char**name)
{
IOERR iRet = RC_SUCCESS;
do
{
RCM(name,iRet,RC_SUCCESS,RC_MSERR_MEMBER_NIL);//check the name is nil? if nil return RC_MSERR_MEMBER_NIL error.
RCM(!*name,iRet,RC_SUCCESS,RC_MSERR_MEMBER_NNIL);//check the *name is nil?if not nil return RC_MSERR_MEMBER_NNIL error(not pointer to nil).
RCM(fullName,iRet,RC_SUCCESS,RC_MSERR_MEMBER_NIL);//check the fullName is nil? if nil return RC_MSERR_MEMBER_NIL error.
unsigned long offset = 0;
if (RtlSsGetLast(fullName,".",&offset))//in the RtlKit
{
RtlSsCopyByOffset(fullName,name,0,offset-1);
}
else
{
RtlSsCopyByLength(fullName,name,strlen(fullName));
}
} while (0);
return iRet;//RCM will jump here if an error happened. RCM is defined by BWI.
}