Introducing AutoTree (Chinese)

AutoTree对象属于特殊引用对象,在使用上它既不同于指针对象,也不同于值对象。它采取半自动内存管理政策,在对其进行赋值时请尤其注意它的引用特性。

注意:本文用到了AutoTree构造语法,这不是标准C的语法,而是为了更简单的实现特定功能创造的语法。


Summary

autotree.h采用特殊的内存区域来存储对象,这块内存区域您无法通过C中常见的指针操作来访问。我在设计AutoTree之初,就期望它可以像JavaScript一样自动管理内存,同时保持优良的对C互操作性。在您使用AutoTree时,大多数时候您可以把AutoTree对象看作是JavaScript中的Json对象来使用。

什么是AutoTree?

AutoTree实际上是对结构体__builtin_generic_AutoTreeNode的别称,其指代树中的一个节点,下文中使用AutoTree也代表节点。AutoTree可以是一个KV对集合,也可以是一个数组,也可以是叶子节点,如一个字符串或一个数字。例如,您有一棵树,只需要持有树的根节点即可完成对其所有节点的访问。所以,对AutoTree的@构造返回的是树的根节点。为了让树的所有节点可以在根节点被销毁时销毁,所以所有的AutoTree对象都包含一个引用计数来计算生命周期。您可以使用int tree_refcnt(AutoTree tree)来获取节点的引用计数。当引用计数为0时该节点被销毁,使用@构造产生的树中,包含头节点在内的所有节点引用计数初始均为1。当该树不再使用时,您需要手动调用void tree_release(AutoTree tree);来删除这棵树。实际上这个函数会将这个节点的引用计数减去一,当节点的引用计数为0时会删除自身,删除自身的同时会给其子节点引用计数减一,利用这个特性,只需要对头节点进行release操作,就可以像多米诺骨牌一样全部删除。

1. @构造

类似于Json,如果您需要构造一棵树,只需要进行:

这样,就诞生了一个有四个节点的树,tree是树的头节点,三个叶子节点分别表示三个值。请不要忘记@符号,这是对额外C语言拓展功能的标志。同时,@构造还可用于数组,数字,字符串以及C表达式。

当然,树是递归定义的,以上特性都可以递归整合在一起,整合的结果可以是如下:

在语义完备的部分情况下(字符串常量的后边),逗号可以省略。(在C Code Develop 3.2以后的版本中,由于为ccdui.h增加了多种AutoTree内置语义,所以不建议在任何地方省略逗号以免发生歧义)

2.常用操作函数

  1. 与Json互操作性
  1. 生命周期
  1. 字符串可操作性

3. 赋值(与C互操作)

上面介绍的path表达式可以直接在C语言中使用,就像对结构体操作那样,例如:

每个AutoTree对象均有一个独特的地址,指向特殊的内存区域。如果有必要,您可以通过__at_handle字段来访问。

有时候,我们可能希望两个树中的某些子树共享一份内存,所以可能存在两棵不同的树的某两个子树的__at_handle字段一样,例如A.a和B.a相同,当我们修改A.a时,B.a就同时被修改,例如JavaScript对象赋值。也有时候,我们不希望共享内存,让两个对象独立发展,所以赋值是一个必须十分小心的事。

深拷贝和浅拷贝
  1. 浅拷贝(引用复制)

    浅拷贝是默认的拷贝模式,当使用等号对一个AutoTree右值赋值时的行为是浅拷贝。

    当使用浅拷贝时,AutoTree会自动的给浅拷贝增加引用计数。

  2. 深拷贝(值复制)

    AutoTree暂时没有深拷贝语法,但是您可以通过tree_clone来实现深拷贝。

    如果您想把tree.b深拷贝到tree.a,请注意引用计数的问题。

赋值的种类

赋值的具体情况种类较为复杂,但AutoTree在赋值的宗旨是尽可能的模拟JavaScript的行为,记住这点就可以了。

以下内容总结了AutoTree对象相关的所有赋值意义,可供查阅。为了支持引用复制,当您使用AutoTree c = tree.b; 时,c变量中会记录自己来自于tree变量的b字段,称c为字典来源。若使用AutoTree c = tree[0],c变量会记录自己来自于tree变量的第0个字段,称c为数组来源。字典来源和数组来源都属于有来源对象,而AutoTree c = @{}; 创建的新树c属于顶级对象,属于无来源对象。这些两组四种不同的特性标志了在赋值的时候具有不同含义,需要注意。

左侧类型右侧类型含义
AutoTree 有来源空AutoTree 任意右侧引用复制到左侧
AutoTree 无来源空AutoTree 任意右侧地址复制到左侧
AutoTree 无来源非空AutoTree 任意右侧第一层值复制到左侧
AutoTree 字典来源非空AutoTree 任意右侧引用复制到左侧,支持新建字段
AutoTree 数组来源非空AutoTree 任意右侧引用复制到左侧,不支持新建字段
AutoTree 字典来源空int | char *赋值(创建新字段)
AutoTree 非空int | char *赋值
int | char *AutoTree 任意拷回C(对字符串创建新的C字符串)

 


See Also

ccdui.h 定义如何创建一个窗口、附加组件树、打开窗口以及进入窗口消息循环的方法

ccduicomp.h 定义了如何构造组件树,及组件树的格式