20.5.11

根据国际法 PK 不要拿法律当挡箭牌

这个是163上的一个新闻。当姜瑜被问及百度公司和中国政府因为网络消息屏蔽被纽约居民起诉时,义正词严的表示:中国政府鼓励和支持互联网发展,依法保障中国公民言论自由。中国政府依法管理互联网符合国际通行做法,属于主权行为,根据国际法,外国法院没有管辖权。

哦,这个时候提及国际法了啊!难道你老人家忘记前不久的至理名言了吗?“不要拿法律当挡箭牌”啊!

看完内容就得看评论嘛!到目前为止,有850人参与,跟贴218条,却仅仅显示了四条回复。这个嘛,这个,这个,这个......



Buzz Delicious Digg it! Facebook Reddit Stumbleupon Technorati Tweet it!

28.4.11

Create Debian and RPM packages using OBS

Have you ever tried to create both Debian and RPM packages using OBS? Well, a little bit different from the package generation locally, but not that much ;)

Before continuing, you should prepare yourself with basic Debian and RPM packaging knowledge.

First, make a tar-ball for your source code, without any packaging information inside. Name it obs-sample.tar.gz.

Then for Debian packaging, you need the following files.
obs-sample_1.0.dsc: indicating you want to create a Debian package; the Files section is not needed, but the Build-Depends section is necessary.
debian.rules: the rules file for Debianization.
debian.control: the control file for Debianization.
debian.tar.gz: all the other files inside the debian folder.

For RPM packaging, you only need the .spec file as expected.

Finally, here goes the simple sample I created. Happy hacking!

Buzz Delicious Digg it! Facebook Reddit Stumbleupon Technorati Tweet it!

21.3.11

利比亚的故事

联合国安理会在3月17日通过1973号决议,对利比亚实施禁飞,并授权采取一切必要措施保护平民和平民居住区免受武装袭击的威胁。

3月18日,利比亚外长穆萨·库萨宣布,利比亚接受联合国安理会有关在利比亚设立禁飞区的决议,立即停火并停止所有军事行动。

3月19日,利比亚政府军进攻反对派大本营班加西,卡扎菲则表示联合国安理会的决议无效(这条新闻在国内媒体的报道几乎都是一笔带过,很少提及)。随后,国际社会开始了对利比亚的军事干预。

此后,卡扎菲表示将打开军火库以武装所有民众,打一场持久战。

3月20日,利比亚武装部队发言人法格希宣布,利比亚政府军于当地时间20日晚9时起执行全面停火,并停止在利比亚境内的一切军事行动。

不放回顾一下早些时候卡扎菲的伟大讲话......
2月24日,卡扎菲在电视讲话中表示基地组织是现在利比亚危机的幕后策划者。

3月8日,卡扎菲表示如果西方设立“禁飞区”逼得太紧,他将与基地组织联手。

末了再来对比一下这几条被国内媒体一笔带过或是干脆不报的新闻......
2月22日,卡扎菲援引六四事件为自己辩护,电视讲话中说,北京的学生在天安门抗议了好几天,中国领导人然后派坦克进入,把学生摧毁、铲除。

2月23日,利比亚飞行员不愿屠杀平民,拒绝执行卡扎菲轰炸班加西的命令弃机跳伞

3月21日,英国空军因在攻击区域发现有平民存在而放弃了攻击任务。

Buzz Delicious Digg it! Facebook Reddit Stumbleupon Technorati Tweet it!

18.1.11

收费公路养活了多少人?

368万天价过路费的事我就不多说了,大家心里都明白。和谐,要和谐啊,莫非要像突尼斯人民一样让总统飞不成?当然了,和谐是和谐,自家的糊涂账是得更忽悠一些的,所以交通运输部副部长翁孟勇就出来澄清了嘛:
我们已经在17个省全部取消了政府还贷的二级公路收费站点,撤销站点1723个,总里程9万公里,这其中解决了40万人过去收费和征稽人员的分流安置工作
算一算,光是这么些个二级公路,每个收费站养活了232个人,每公里更是养活了4.4个人,厉害啊!

Buzz Delicious Digg it! Facebook Reddit Stumbleupon Technorati Tweet it!

11.12.10

我最崇拜的人姓刘

所有内容摘自互联网,感谢各位网友的原创!持续更新中;)

我最崇拜的人姓刘,他获得过国际大奖,他的所作所为激发了国人的斗志,虽然有一段时间他从我们眼前消失了,但是我相信他的精神永存。他的名字叫刘翔。

我最崇拜的人姓刘,他领导过学生闹学运,出过书,得过外国的奖,后来被冤枉做了很多年牢。但我相信,这些都是历史给他的考验,因为他说过,好在历史是人民写的。他的名字是刘少奇。

我最崇拜的人姓刘。他是个博士,他出过书、当过被告。得过西方很多国家的大奖,以及香港台湾等境外组织颁发的奖。他是很多中国人的偶像,他是中国人的自豪和骄傲。他叫刘德华!

我最崇拜的人姓刘,ta面对暴力无所畏惧,坚定信仰自己的理念。尽管ta早早地被强权迫害,但ta的名字直到今天仍在流传。ta是刘胡兰。

我最崇拜的人姓刘,出过书,获得过国际大奖,用多年的拼搏和追求向世界展示国人的无悔青春,虽然有一段时间住过牢,但是我相信特不会为此而向命运屈服。特的名字是刘晓庆。

我最崇拜的人姓刘,他获得了世界性的奖项,因为他的推手技惊全球以至于不得不说:我没有敌人。有时候面对记者会结结巴巴,他一度消失在人们的视野。整个世界都经常默念他的名字:国家的未来栋梁!他的名字叫刘国梁。

我最崇拜的人姓刘,他十几年如一日,忍辱负重,勤奋耕耘,从一个东北土鳖成长为亿万人瞩目的理性楷模。他致力于一个理想化的行动,让自己备受磨难,但人们心里为他树起了一座丰碑,他的名字叫刘老根儿。

我最崇拜的人他姓刘,他一生传奇,80年代就名扬国际,热衷挑战强拳,获得过无数国际大奖。他的一生没有敌人。他就是拳王刘易斯。

我崇拜的人姓刘,从80年代开始就写出了一系列传世佳作,在一代又一代爱好自由的人手中传颂。尽管关于他的作品有一些争议,但好无偏见的说他的文字影响和改变了很多推友。他就是刘欣慈。

我最崇拜的人姓刘,他获得过很多境外组织的奖杯,他的作品流行海内外,他忠厚的面貌总是让人感到亲切,他也很关心缅甸昂山阿姨的情况,他的名字叫刘青云。

我最崇拜的人姓刘,他以人性化的实践,经历和见证了封建小农经济下个人良心的最大发挥。他清白而廉洁,但却历经诬陷,一个好人被钉在耻辱里,体现了专制政权的强横与无耻。然而,他被人传颂为良知的化身和尊严的维护者。他的名字叫刘文彩。

我不崇拜的人姓刘,他某年因为因为被央视现场报道使用幕后黑手欺骗全国人民而一举闻名。他荣获过那个领域的国际大奖,他的成就可以说在中国没有敌人。网上关于他的争议一直很多,不过丝毫不影响他的影响力。他就魔术师刘谦。

我最崇拜的人姓刘,ta是一个东北人,ta于1989年春夏之交正式登上历史舞台,ta在世界上拥有极高的声望,ta就是我国著名游泳运动员刘子歌。

我最崇拜的人姓刘,他为了反抗强权暴政忍辱负重,尽管他有很多先天缺陷,但是仍然不能阻止他成为时代的领袖,他的名字刘邦。

我最崇拜的人姓刘,虽然我没有见过他,但他一直为大家的幸福生活在默默的努力。现在越来越多的人知道他喜欢他的作品,甚至还有人盗版他的东西冒充来卖,这是一件好事,他叫刘一手。

我最崇拜的人姓刘,Ta和Ta的同志们为了自由和人权与专制进行了不懈的斗争,Ta用自身惨痛的牺牲证明了专制的残暴,人们铭记着Ta的事迹,专制却从学校课本里把Ta的名字拿走,Ta的名字叫刘和珍。

我最崇拜的人姓刘,每当我觉得社会太黑暗、生活得太辛苦要放弃时,脑海中出现ta的身影又让我重燃斗志。ta是刘亦菲。

我最崇拜的人姓刘。念过大学,刚正不阿,曾被当权者剥夺工作,中年后又被关入监狱。每个中国人都应该记住他的名字。他叫刘墉!

我最崇拜的人姓刘,ta很早就被黑恶势力打压,登上封面,影响很坏,因此消失了很长时间,但是最近ta又出来了,还获得了很多奖项,跟影帝结合了,ta叫刘嘉玲。

Buzz Delicious Digg it! Facebook Reddit Stumbleupon Technorati Tweet it!

7.12.10

The Beauty of Qt 3: Implicit Sharing

To maximize resource usage and minimize copying, Qt uses implicit data sharing in many classes, so that the data is copied only when a function writes to it. This trick is also referred to as flyweight pattern sometimes.

Now let's take QByteArray as an example to see how it's implemented. It uses a private struct of Data to track the shared data:
struct Data {
  QBasicAtomicInt ref; // reference count, the operation on it is atomic
  int alloc; // allocated space for the data
  int size; // actual size of the data, not counting the ending '\0' added by QByteArray
  char *data; // point to the data
  char array[1]; // where the data is stored, and the data always end with '\0'
};


Here, we use both the pointer of data and array just because the data might actually be stored in another object. When an object is copied, e.g. through the assignment operator, it only copies the pointer to the shared data:
QByteArray &QByteArray::operator=(const QByteArray & other)
{
  // increase the reference count of the shared data it's supposed to be used
  other.d->ref.ref();

  // decrease the reference count of the share data currently used, and free it if no one else is using
  if (!d->ref.deref())
    qFree(d);

  // point to the shared data
  d = other.d;

  return *this;
}


On the other hand, if it's to be changed by e.g. the resize() function, it copies the data if any other object also shares it:
void QByteArray::resize(int size)
{
  if (size <= 0) {
    // if the target is no bigger than 0, points to an empty data block
    Data *x = &shared_empty;
    x->ref.ref();
    if (!d->ref.deref())
      qFree(d);
    d = x;
  } else if (d == &shared_null) {
    // if currently a null array, just create a new data block
    Data *x = static_cast<data *>(qMalloc(sizeof(Data)+size));
    Q_CHECK_PTR(x);
    x->ref = 1;
    x->alloc = x->size = size;
    x->data = x->array;
    x->array[size] = '\0';
    (void) d->ref.deref();
    d = x;
  } else {
    // if any other object uses this data block, or the current memory is too small or too big
    // reallocate space, and copy the data for it
    // note that this operation might consume some time if the data is huge
    if (d->ref != 1 || size > d->alloc || (size < d->size && size < d->alloc >> 1))
      realloc(qAllocMore(size, sizeof(Data)));
    if (d->alloc >= size) {
      d->size = size;
      if (d->data == d->array) {
        d->array[size] = '\0';
      }
    }
  }
}


With this in mind, let's see how to use QSharedData and QSharedDataPointer to implement our own implicit shared data objects.
// first implement your data object inheriting from QSharedData, which provides the reference count
class SharedData: public QSharedData
{
public:
  SharedData()
    : QSharedData()
    , var(0)
  {}

  SharedData(const SharedData &other)
    : QSharedData(other)
    , var(other.var)
  {}

  int var;
};

// then the data owner
class DataOwner
{
public:
  DataOwner()
  : d(new SharedData)
  {}

  DataOwner(int var)
  : d(new SharedData)
  {
    // for write access, the -> operator will automatically copy the shared data if needed
    d->var = var;
  }

private:
  // this template class hides all the details for implicit sharing
  // therefore, no need to provide copy constructor or assignment operator
  QSharedDataPointer<SharedData> d;
};


Quite simple, right ;) Then just proceed to implement explicit shared data objects using QExplicitlySharedDataPointer yourself.

Buzz Delicious Digg it! Facebook Reddit Stumbleupon Technorati Tweet it!

1.12.10

The Beauty of Qt 2: Meta Object

Besides the D-pointers, another interesting thing in Qt is the Q_OBJECT macro. It provides the access to meta objects, which enables you to enjoy more features of a QObject, e.g. signals and slots. The meta object provides information about class name, properties and methods of a QObject, which is also known as reflection.

Using QMetaObject, you can print the information of the class name, etc.:
QObject obj;
const QMetaObject *metaObj = obj.metaObject();
qDebug() << "class name: " << metaObj->className();
qDebug() << "class info count: " << metaObj->classInfoCount();
qDebug() << "methods: ";
// starting from QMetaObject::methodOffset() so it won't display the methods inherited
for (int i = metaObj->methodOffset(); i < metaObj->methodCount(); ++i)
  qDebug() << metaObj->method(i).methodType() << " " << metaObj->method(i).signature();


As none of these information is supported in pure C++, Qt uses the Meta Object Compiler (moc) to do all the tricks. It reads each header file, and generates a C++ source file (moc_*.cpp) containing the code for meta-object, if it finds a Q_OBJECT macro used in any class declaration. With the code generation approach, Qt not only gains the flexibility as in e.g. Java, but also keeps the performance and scalability as in C++.

Suppose we have the following simple class:
class MyObject : public QObject
{
  Q_OBJECT
public:
  explicit MyObject(QObject *parent = 0);

  void myFunc();

public slots:
  void mySlot(int myParam);

signals:
  void mySignal(int myParam);
};


The following code / information will be generated by moc, and can be retrieved through pointers defined in the anonymous struct of QMetaObject::d:
// pointed by QMetaObject::d.data, the beginning stored "as" a QMetaObjectPrivate struct
static const uint qt_meta_data_MyObject[] = {
  5, // revision, the internals have been changed several times
  0, // classname, offset of qt_meta_stringdata_MyObject

  // the following are defined as (number, index) pair
  0, 0, // classinfo
  2, 14, // we have two methods, starting at index 14 (i.e. the signal)
  0, 0, // properties
  0, 0, // enums/sets
  0, 0, // constructors

  0, // flags
  1, // signal counts

  // for signals slots, and properties, the signatures and parameters are offset of qt_meta_stringdata_MyObject
  // signals: signature, parameters, type, tag, flags
  18, 10, 9, 9, 0x05,

  // slots: signature, parameters, type, tag, flags
  32, 10, 9, 9, 0x0a,

  0 // eod
};

// pointed by QMetaObject::d.stringdata
static const char qt_meta_stringdata_MyObject[] = {
  "MyObject\0\0myParam\0mySignal(int)\0"
  "mySlot(int)\0"
};


The above information, as well as the information for its base class, is stored as the static meta object for this class:
const QMetaObject MyObject::staticMetaObject = {
  { &QObject::staticMetaObject, // pointer to its base class, stored at QMetaObject::d.superdata
    qt_meta_stringdata_MyObject, qt_meta_data_MyObject, 0 }
};


In this way, if you want to do type cast for QObject, instead of using the somewhat expensive operator of dynamic_cast, we can use qobject_cast. It exploits the benefits of the meta object system, thus avoiding the runtime type cast:
template <class T> inline T qobject_cast(QObject *object)
{
#if !defined(QT_NO_QOBJECT_CHECK)
  reinterpret_cast(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast(object));
#endif
  return static_cast(reinterpret_cast(0)->staticMetaObject.cast(object));
}


Here, the trick is that the QMetaObject of the target type checks if the object inherits from it:
const QObject *QMetaObject::cast(const QObject *obj) const
{
  if (obj) {
    const QMetaObject *m = obj->metaObject();
    do {
      if (m == this)
        return obj;
    } while ((m = m->d.superdata));
  }
  return 0;
}


Also, moc will generate some code for each signal. Whenever a signal is emitted, this function will be called internally:
void MyObject::mySignal(int _t1)
{
  void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
  // it checks all the connected slots, and call each of them based on the connection type
  QMetaObject::activate(this, &staticMetaObject, 0, _a);
}


In the end, the slots are invoked by the generated qt_metacall function:
int MyObject::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
  // if this function is called by the super class, just return
  _id = QObject::qt_metacall(_c, _id, _a);
  if (_id < 0)
    return _id;

  // call the function based on its ID
  if (_c == QMetaObject::InvokeMetaMethod) {
    switch (_id) {
    case 0: mySignal((*reinterpret_cast< int(*)>(_a[1]))); break;
    case 1: mySlot((*reinterpret_cast< int(*)>(_a[1]))); break;
    default: ;
    }

    // remove the IDs "consumed" by this class so that in its subclass the ID always starts with 0, and the return value of -1 means already consumed
    _id -= 2;
  }

  return _id;
}


Buzz Delicious Digg it! Facebook Reddit Stumbleupon Technorati Tweet it!