Aug
3
svn的diff很好用,但是还不够好用,因为不像vim,可以很直观地看到两个文件的区别。Google了一下,发现一个还不错的解决方案( http://erik.thauvin.net/blog/news.jsp?date=2006-02-14 ),代码在这里: http://vc.thauvin.net/svn/linux/svndiff/svndiff.sh?view=markup ,但是有点小BUG。我FIX了一下,然后增加了一个小feature,允许在命令行后面跟上 "-r REV" 来指定与最新版本比较的版本号。代码如下:
@p.s. 2010.8.4 昨天给Erik发了封邮件,今天发现他已经把我的修改更新进去了:D
#!/bin/sh
# svndiff -- svn diff with vimdiff.
#
# Written by Erik C. Thauvin (erik@thauvin.net)
# May 11, 2006
#
# Copyright (C) 2006 Erik C. Thauvin. All rights reserved.
#
# This software is provided "as is" without express or implied warranties.
#
# Permission is granted to use, copy, modify and distribute this software,
# provided this disclaimer and copyright are preserved on all copies. This
# software may not, however, be sold or distributed for profit, or included
# with other software which is sold or distributed for profit, without the
# permission of the author.
#
# $Id$
#
# Modified by felix021 (felix021@gmail.com)
# Aug 3, 2010
PROGNAME=`basename $0`
if [ $# -lt 1 ]; then
echo "Usage: $PROGNAME <file> [-r REV]"
exit;
fi
filename=$1
pid=$$
TEMP=/tmp/tmp.$pid.$filename
pv=
if [ $# -gt 3 -a $2 = "-r" ]; then
pv="-r $3"
fi
svn cat $filename $pv > $TEMP
vimdiff $TEMP $filename
rm -f $TEMP
# svndiff -- svn diff with vimdiff.
#
# Written by Erik C. Thauvin (erik@thauvin.net)
# May 11, 2006
#
# Copyright (C) 2006 Erik C. Thauvin. All rights reserved.
#
# This software is provided "as is" without express or implied warranties.
#
# Permission is granted to use, copy, modify and distribute this software,
# provided this disclaimer and copyright are preserved on all copies. This
# software may not, however, be sold or distributed for profit, or included
# with other software which is sold or distributed for profit, without the
# permission of the author.
#
# $Id$
#
# Modified by felix021 (felix021@gmail.com)
# Aug 3, 2010
PROGNAME=`basename $0`
if [ $# -lt 1 ]; then
echo "Usage: $PROGNAME <file> [-r REV]"
exit;
fi
filename=$1
pid=$$
TEMP=/tmp/tmp.$pid.$filename
pv=
if [ $# -gt 3 -a $2 = "-r" ]; then
pv="-r $3"
fi
svn cat $filename $pv > $TEMP
vimdiff $TEMP $filename
rm -f $TEMP
@p.s. 2010.8.4 昨天给Erik发了封邮件,今天发现他已经把我的修改更新进去了:D
Jul
29
1. 下载gdi+的sdk,安装。当然,可以简化一点,从这里[ http://download.csdn.net/down/1645798/huohuo1120 ]下载gdiplus所需文件包,解压并导入到vc6(将include和lib目录加入vc6的配置中)
2. 在VC6中创建一个Win32 Application,选择“一个简单的Win32程序”。假设项目名是main
3. 在StdAfx.h中加入
4. 在main.cpp的WinMain前面生命全局的两个GDI变量
5. 在程序退出之前的地方加上
6. 画图
6.1 创建一个Bitmap对象
6.2 从Bitmap中获取Graphics对象
6.3 使用各种东西的组合来搞g,比如Pen, Brush, Region, Rect, PointF, Font……
7. 保存文件,这个比较麻烦
2. 在VC6中创建一个Win32 Application,选择“一个简单的Win32程序”。假设项目名是main
3. 在StdAfx.h中加入
#include <winbase.h>
#define UNICODE
#include <comdef.h>
#ifndef ULONG_PTR
#define ULONG_PTR unsigned long*
#include <GdiPlus.h>
using namespace Gdiplus;
#endif
#define UNICODE
#include <comdef.h>
#ifndef ULONG_PTR
#define ULONG_PTR unsigned long*
#include <GdiPlus.h>
using namespace Gdiplus;
#endif
4. 在main.cpp的WinMain前面生命全局的两个GDI变量
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
ULONG_PTR gdiplusToken;
5. 在程序退出之前的地方加上
GdiplusShutdown(gdiplusToken);
6. 画图
6.1 创建一个Bitmap对象
Bitmap *pBitmap = new Bitmap(width, height, PixelFormat24bppRGB);
6.2 从Bitmap中获取Graphics对象
Graphics *g = Graphics::FromImage(pBitmap);
6.3 使用各种东西的组合来搞g,比如Pen, Brush, Region, Rect, PointF, Font……
Pen pen_black(Color(255, 0, 0, 0), 3);
g->DrawLine(&pen_black, 0, 0, 100, 100);
更具体的说明和各种例子可以在这里找到:GDI+ SDK参考(翻译版本) http://download.csdn.net/source/642128g->DrawLine(&pen_black, 0, 0, 100, 100);
7. 保存文件,这个比较麻烦
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num= 0, size= 0;
ImageCodecInfo* pImageCodecInfo= NULL;
GetImageEncodersSize(&num, &size);
if(size== 0)
return -1;
pImageCodecInfo= (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo== NULL)
return -1;
GetImageEncoders(num, size, pImageCodecInfo);
for(UINT j=0; j< num; ++j)
{
if(wcscmp(pImageCodecInfo[j].MimeType, format)== 0)
{
*pClsid= pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j;
}
}
free(pImageCodecInfo);
return -1;
}
......
CLSID encoder;
GetEncoderClsid(L"image/png", &encoder); // L"image/jpeg", ...
pb->Save(L"result.png", &encoder, NULL);
{
UINT num= 0, size= 0;
ImageCodecInfo* pImageCodecInfo= NULL;
GetImageEncodersSize(&num, &size);
if(size== 0)
return -1;
pImageCodecInfo= (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo== NULL)
return -1;
GetImageEncoders(num, size, pImageCodecInfo);
for(UINT j=0; j< num; ++j)
{
if(wcscmp(pImageCodecInfo[j].MimeType, format)== 0)
{
*pClsid= pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j;
}
}
free(pImageCodecInfo);
return -1;
}
......
CLSID encoder;
GetEncoderClsid(L"image/png", &encoder); // L"image/jpeg", ...
pb->Save(L"result.png", &encoder, NULL);
Jul
27
在ISO C规范中有有一个很诡异的东西,那就是传说中的errno,一个有左值的int。当库函数出错的时候,它很可能会被设置为非0值;且没有任何一个库函数或系统调用会把它置为0。
刚接触到errno,可能会认为这是个在errno.h中用
幸而,ISO C并没有规定,errno必须是一个int,如果看errno的manpage (man errno) 会看到:实际上GNU的glibc也就是这么实现的,(通常)在/usr/include/bits/errno.h里头:
于是errno就是个有左值的int了。至于这个__errno_location,在glibc的源码的 csu/errno-loc.c 里头:
而这里的真正的errno,在 csu/errno.c 里头:
由于包含的都是errno.h,所以对于用户程序而言,可见的只有errno.h中的"errno",实际上是(*(__errno_location()),而__errno_location()返回的是errno.c中的errno的地址。可真绕啊。可是偏偏又不能把 __thread int errno; 放在errno.h中,为什么呢?其实原因很简单也很复杂——C语言真是个纠结的语言。
最后,解释一下“__thread”修饰符:__thread defines number to be a thread local variable. 定义thread-local的变量。详情参见Thread-local_storage的wiki页:http://en.wikipedia.org/wiki/Thread-local_storage
刚接触到errno,可能会认为这是个在errno.h中用
int errno;
定义的整型。但是一旦开始写多线程的程序,再看到errno的时候,就会抑郁了。如果两个线程调用库函数都出错,那errno怎么办...?幸而,ISO C并没有规定,errno必须是一个int,如果看errno的manpage (man errno) 会看到:
引用
errno may be a macro. errno is thread-local; setting it in one thread does not affect its value in any other thread.
#define errno (*__errno_location ())
于是errno就是个有左值的int了。至于这个__errno_location,在glibc的源码的 csu/errno-loc.c 里头:
int *
#if ! USE___THREAD
weak_const_function
#endif
__errno_location (void)
{
return &errno;
}
#if ! USE___THREAD
weak_const_function
#endif
__errno_location (void)
{
return &errno;
}
而这里的真正的errno,在 csu/errno.c 里头:
__thread int errno;
由于包含的都是errno.h,所以对于用户程序而言,可见的只有errno.h中的"errno",实际上是(*(__errno_location()),而__errno_location()返回的是errno.c中的errno的地址。可真绕啊。可是偏偏又不能把 __thread int errno; 放在errno.h中,为什么呢?其实原因很简单也很复杂——C语言真是个纠结的语言。
最后,解释一下“__thread”修饰符:__thread defines number to be a thread local variable. 定义thread-local的变量。详情参见Thread-local_storage的wiki页:http://en.wikipedia.org/wiki/Thread-local_storage
Jul
21
0. int fd[2];
1. pipe(fd) 打开一个管道
2. fork或者pthread
3. 往fd[0]写字符串
4. 从fd[1]读取,或者可以fdopen(fd[1]),获得一个文件指针,读取文件。
1. pipe(fd) 打开一个管道
2. fork或者pthread
3. 往fd[0]写字符串
4. 从fd[1]读取,或者可以fdopen(fd[1]),获得一个文件指针,读取文件。
Jul
20
纯粹记录一下。看不懂的绕行吧..
当客户端COMMIT成功以后,post-commit会被执行,调用时会传入两个参数,$1是repos的绝对路径,$2是REV,此次提交的版本号。
可以配合rsync用于分发各种东西。
$ mkdir repos
$ svnadmin create repos
$ ls repos/
conf db format hooks locks README.txt
$ ls repos/hooks/
post-commit.tmpl post-revprop-change.tmpl pre-commit.tmpl pre-revprop-change.tmpl start-commit.tmpl
post-lock.tmpl post-unlock.tmpl pre-lock.tmpl pre-unlock.tmpl
$ cd repos/hooks
$ cp post-commit.tmpl post-commit
$ chmod +x post-commit
$ vi post-commit
……
$ svnadmin create repos
$ ls repos/
conf db format hooks locks README.txt
$ ls repos/hooks/
post-commit.tmpl post-revprop-change.tmpl pre-commit.tmpl pre-revprop-change.tmpl start-commit.tmpl
post-lock.tmpl post-unlock.tmpl pre-lock.tmpl pre-unlock.tmpl
$ cd repos/hooks
$ cp post-commit.tmpl post-commit
$ chmod +x post-commit
$ vi post-commit
……
当客户端COMMIT成功以后,post-commit会被执行,调用时会传入两个参数,$1是repos的绝对路径,$2是REV,此次提交的版本号。
可以配合rsync用于分发各种东西。
Jul
19
前一阵和momo讨论到他的基于UDP的某个系统的设计时遇到这样一个问题:在一个局域网中有多台机器,有个消息是通过UDP广播发出的,且每台机器有多个进程需要监听同一个UDP端口,应该怎么办?
由于所知有限,当时我给的解决方案是,使用类似observer模式来建立一个稍复杂的服务(其实就是个转发,但是UDP进程数量未知)。后来momo发现,其实只要通过setsockopt设置SO_REUSEADDR属性之后,多个程序就可以绑定同一个端口了。
虽然问题是解决了,但是SO_REUSEADDR并没有上面提到的那么简单,因为momo遇到的问题正好是UDP广播/多播。否则上述模型就不适用了。这里有一篇文章,对其有更详细的注解,虽然是摘自《UNIX网络编程》的,但是给出了例子,很值得学习。
SO_REUSEADDR例解:http://www.cppblog.com/ace/archive/2006/04/29/6446.aspx
unix网络编程 第一卷:http://wenku.baidu.com/view/99a6cc38376baf1ffc4fad6f.html
由于所知有限,当时我给的解决方案是,使用类似observer模式来建立一个稍复杂的服务(其实就是个转发,但是UDP进程数量未知)。后来momo发现,其实只要通过setsockopt设置SO_REUSEADDR属性之后,多个程序就可以绑定同一个端口了。
虽然问题是解决了,但是SO_REUSEADDR并没有上面提到的那么简单,因为momo遇到的问题正好是UDP广播/多播。否则上述模型就不适用了。这里有一篇文章,对其有更详细的注解,虽然是摘自《UNIX网络编程》的,但是给出了例子,很值得学习。
SO_REUSEADDR例解:http://www.cppblog.com/ace/archive/2006/04/29/6446.aspx
unix网络编程 第一卷:http://wenku.baidu.com/view/99a6cc38376baf1ffc4fad6f.html
Jul
8
在不是用iframe测试iframe app的时候(就是在新窗口打开iframe的url)可以在地址栏执行用这种方式(注:$是jQuery里头的函数)javascript:$('#id')[0].style.visibility='hidden'; 可以让某个元素不可见,但是再次改为visible时不会需要重新载入。IE8、FF3.5、Chrome5测试通过。
FB.login(cb, {perms:'perm1,perm2,...'}) 给cb的参数response的属性perms 【如function cb(response){ alert(response.perms); }】 包含的是所有授权的perms列表,逗号分隔;无论这次login方法请求的perms是多少个。
javascript:FB.api({ method: 'Auth.revokeAuthorization' });
来取消所有已经取得的权限,包括Basic Info、Bookmark,当刷新apps.facebook.com/xxxx的时候会要求重新认证。再未重新认证时如果在非iframe的方式测试FB.ui({method:'bookmark.add'}, cb)会出现引用
An error occurred with APP_NAME. Please try again later.
API Error Code: 200
API Error Description: Permissions error
Error Message: Permissions error
API Error Code: 200
API Error Description: Permissions error
Error Message: Permissions error
FB.login(cb, {perms:'perm1,perm2,...'}) 给cb的参数response的属性perms 【如function cb(response){ alert(response.perms); }】 包含的是所有授权的perms列表,逗号分隔;无论这次login方法请求的perms是多少个。
Jul
8
facebook的javascript sdk因为需要完成比较多的功能,因此体积比较大(50K左右)。
如果每次都完整载入,必然会导致浪费过多带宽,因此缓存是必要的;但是缓存会导致BUG fix或者function enhancement无法即时更新到客户端。二者之间的矛盾调和可以用调整缓存时间来解决,但是这种解决方案并不够好,尤其是灵活性不够,有时候lib一天更新几次,有时候十天半个月甚至更久都不更新,这种解决方案的适应性就不够了。
facebook用的解决方案是,将sdk进行拆分,变成两块,第一块是loader,约2KB,缓存时间1小时;第二块是lib,约50KB,缓存时间一个月。开发者只需要用script标签载入loader即可,由loader来载入lib。lib的路径是带有版本号的,当facebook更新了lib以后,只需要修改loader中lib的版本。由于版本号不同了,路径也不同了,因此浏览器会重新请求新版本的lib。
该思路摘自facebook的wiki:http://wiki.developers.facebook.com/index.php/FeatureLoader.js.php
p.s. 这个是旧版的SDK。
如果每次都完整载入,必然会导致浪费过多带宽,因此缓存是必要的;但是缓存会导致BUG fix或者function enhancement无法即时更新到客户端。二者之间的矛盾调和可以用调整缓存时间来解决,但是这种解决方案并不够好,尤其是灵活性不够,有时候lib一天更新几次,有时候十天半个月甚至更久都不更新,这种解决方案的适应性就不够了。
facebook用的解决方案是,将sdk进行拆分,变成两块,第一块是loader,约2KB,缓存时间1小时;第二块是lib,约50KB,缓存时间一个月。开发者只需要用script标签载入loader即可,由loader来载入lib。lib的路径是带有版本号的,当facebook更新了lib以后,只需要修改loader中lib的版本。由于版本号不同了,路径也不同了,因此浏览器会重新请求新版本的lib。
该思路摘自facebook的wiki:http://wiki.developers.facebook.com/index.php/FeatureLoader.js.php
p.s. 这个是旧版的SDK。