POCO C++库学习和分析 -- 数据类型转换POCO C库学习和分析 -- 数据类型转换文章写到这里,Foundation库中的
POCO C++库学习和分析 -- 数据类型转换
POCO C++库学习和分析 -- 数据类型转换
文章写到这里,Foundation库中的功能已经介绍过半了。在接下去介绍其他模块之前,我们先来回顾一下前面的内容。前面的内容包括了:
1. SharedLibrary模块(插件技术) 《Foundation库SharedLibrary模块分析》
2. 线程(锁,线程,线程池,定时器,任务,主动对象) 《线程》
3. 内存管理(智能指针,内存池,自动释放的对象池,对象工厂) 《内存管理》
4. 进程(进程,进程通讯) 《进程》
5. 消息和事件(同步/异步消息传递,消息队列) 《通知和事件》
有了这些模块,我们就可以搭建起一个本地程序的框架了(当然这不包括绘图和显示,Poco库不提供这些功能)。程序的框架很重要,就如同人的骨架和血液一样,决定了一个程序的结构,间接的影响了程序的可修改性和可维护性,但这还不够,要写出一个完整的程序,我们还需要其他的一些部分,这些部分也很重要,就如同人的肌肉和衣服。
下面介绍Foundation库中关于转换的几个类:
1. ByteOrder ByteOrder提供了一系列的静态函数用于字节序的转换。在使用这个类之前,让我们先了解一下它所解决问题。它主要用来解决big-endian和litter-endian的问题。
1.1 big-endian和litter-endian big-endian和litter-endian指的是读取存储时的数据解释方式。它们只和多字节类型的数据有关,比如说int,short,long型,而对单字节数据byte却没有影响。
litter-endian:将低序字节存储在起始地址(低位字节存储在内存中低位地址)。
big-endian:将高序字节存储在起始地址(高位字节存储在内存中低位地址)。
举个例子,int a = 0x01020304
在BIG-ENDIAN的情况下存放为:
字节号 0 1 2 3
数据 01 02 03 04
在LITTLE-ENDIAN的情况下存放为:
字节号 0 1 2 3
数据 04 03 02 01
再举一个,int a = 0x1234abcd
在BIG-ENDIAN的情况下存放为:
字节号 0 1 2 3
数据 12 34 ab cd
在LITTLE-ENDIAN的情况下存放为:
字节号 0 1 2 3
数据 cd ab 34 12
1.2 主机序和网络序 主机序是读取计算机内存数据时的解释方式,它和CPU、操作系统的类型相关,分为litter-endian和big-endian。X86架构的cpu不管操作系统是NT还是UNIX系的,都是小字节序,而PowerPC 、SPARC和Motorola处理器则很多是大字节序。下面是一张字节序和CPU、操作系统的关系表。
处理器 操作系统 字节排序
Alpha 全部 Little endian
HP-PA NT Little endian
HP-PA UNIX Big endian
Intelx86 全部 Little endian (x86系统是小端字节序系统)
Motorola680x() 全部 Big endian
MIPS NT Little endian
MIPS UNIX Big endian
PowerPC NT Little endian
PowerPC 非NT Big endian (PPC系统是大端字节序系统)
RS/6000 UNIX Big endian
SPARC UNIX Big endian
IXP1200 ARM核心 全部 Little endian
1.3 主机序和网络序和大头小头引起的问题 如果在两台字节序不同的主机之间进行网络通讯,大小字节序的问题就会出现。通常的做法是在小字节序一端的主机进行处理,小字节序的主机在发送数据前,转换数据为大字节序,而在接受时,把大字节序数据转成小字节序。
如果在字节序相同的两台机器之间进行通讯,可以不用考虑字节序问题。
同样的是在两台机器之间,用java语言编写通讯程序时,可以不考虑字节序问题。JAVA字节序与网络字节序都是big-endian.
1.4 ByteOrder静态函数 ByteOrder提供了一组静态的Api去解决这个问题。
1) IntXX flipBytes(IntXX value)
字节翻转排序,实现大小字节序的转换
2) IntXX toBigEndian(IntXX value)
把数据从本机序转成大字节序。如果本机序是本身就是大字节序,返回结果为转之前数据。
3) IntXX toLittleEndian(IntXX value)
把数据从本机序转成小字节序。如果本机序是本身就是小字节序,返回结果为转之前数据。
4) IntXX fromBigEndian(IntXX value)
把数据从大字节序转成本机序。如果本机序是本身就是大字节序,返回结果为转之前数据。
5) IntXX fromLittleEndian(IntXX value)
把数据从小字节序转成本机序。如果本机序是本身就是小字节序,返回结果为转之前数据。
6) IntXX toNetwork(IntXX value)
把数据从本机序转成网络序。如果本机序是本身就是大字节序,返回结果为转之前数据。
7) IntXX fromNetwork(IntXX value)
把数据从网络序转成本机序。如果本机序是本身就是大字节序,返回结果为转之前数据。
下面来看一个ByteOrder的例子:
3. DynamicAny Poco::DynamicAny在generic type的处理思路上采用的是上述第一种和第二种思路的结合。
首先它支持有限类型之间的自动类型转换,可以保存一个(int)5进去,读一个(string)"5"出来。所谓有限类型很好理解,因为类型转化的本质是对内存数据的不同解释,如果转化前的数据类型和转化后的数据类型都是不定且无限,作为类的书写者,实在是不能想象的。而有限类型的转化至少我们可以枚举,而事实上这正是Poco::DynamicAny实现时所做的。Poco::DynamicAny支持Int8、Int16、Int32、Int64UInt8、UInt16、UInt32、UInt64、bool、float、double、char、std::string、long、unsigned long、std::vector<T>、DateTime、LocalDateTime、Timestamp类型之间的转化。为此Poco::DynamicAny提供了成员函数convert和operator T()函数去实现上述的功能。当转换失败的时候会抛出异常。
第二,在有限类型内部,Poco::DynamicAny提供函数完成与Poco::Any类类似的功能。事实上DynamicAny::extract()函数和Any类的友元函数AnyCast()是基本一致的。下面是二者代码:
在介绍完这个类之前提一句,有兴趣的同学也可以去考察一下boost库中的boost::variant和boost::lexical_cast,看一看它们和Poco::DynamicAny的异同。
(版权所有,转载时请注明作者和出处 http://blog.csdn.net/arau_sh/article/details/8638475)