Skip to content

Instantly share code, notes, and snippets.

@qingfeng
Created August 11, 2008 14:47
Show Gist options
  • Save qingfeng/4865 to your computer and use it in GitHub Desktop.
Save qingfeng/4865 to your computer and use it in GitHub Desktop.
Hello Objective-C
#!/bin/sh
gcc -o hello cocoa1.m -lobjc -framework Cocoa
#import <Cocoa/Cocoa.h>
int main(){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
printf("Hello, world.\n");
[pool release];
return 0;
}
#import <Foundation/NSObject.h>
@interface Fraction: NSObject {
int numerator;
int denominator;
}
-(void) print;
-(void) setNumerator: (int) d;
-(void) setDenominator: (int) d;
-(int) numerator;
-(int) denominator;
@end
#import "Fraction.h"
#import <stdio.h>
@implementation Fraction
-(void) print {
printf( "%i/%i", numerator, denominator );
}
-(void) setNumerator: (int) n {
numerator = n;
}
-(void) setDenominator: (int) d {
denominator = d;
}
-(int) denominator {
return denominator;
}
-(int) numerator {
return numerator;
}
@end
#import <stdio.h>
int main( int argc, const char *argv[] ) {
printf( "hello world\n" );
return 0;
}
#include <objc/Object.h>
@interface Foo: Object {
int val;
}
-init :(int) v;
-add :(int) v;
-(int) value;
@end
@implementation Foo
-init :(int) v { val = v; return self; }
-add :(int) v { val += v; return self; }
-(int) value { return val; }
@end
@interface Bar: Foo {}
@end
@implementation Bar
-add :(int) v { val -= v; return self; }
@end
int main() {
id obj = [[Bar alloc] init :20];
[obj add :15];
printf("%d\n", [obj value]);
return 0;
}
#import <stdio.h>
#import <objc/Object.h>
@protocol ClassNameToString
- (id) ToString;
@end
@interface A : Object
{
char *name;
}
- (id) init;
- (id) free;
@end
@interface B : Object
@end
@implementation A
- (id) init {
[super init];
name = (char *)malloc(255);
sprintf(name , "%s . A@%d" , __FILE__ , self);
return self;
}
- (id) free {
free(name);
return [super free];
}
- (id) ToString { return (id) name; }
@end
@implementation B
- (id) ToString { return (id)"This is Object of B Class"; }
@end
int main() {
id objA = [A new];
id objB = [B new];
printf("objA = %s\n" , [objA ToString]);
printf("objB = %s\n" , [objB ToString]);
[objA free];
[objB free];
return 0;
}
#import <stdio.h>
#import <objc/Object.h>
@protocol ProtocolA
- (void) MethodA;
@end
@protocol ProtocolB
- (void) MethodB;
@end
@protocol ProtocolC <ProtocolA>
- (void) MethodC;
@end
@interface Test : Object <ProtocolB, ProtocolC>
@end
@implementation Test
- (void) MethodA { printf("This is MethodA\n"); }
- (void) MethodB { printf("This is MethodB\n"); }
- (void) MethodC { printf("This is MethodC\n"); }
@end
int main() {
id obj = [Test new];
[obj MethodA];
[obj MethodB];
[obj MethodC];
[obj free];
return 0;
}
#import <stdio.h>
#import "Fraction.h"
int main( int argc, const char *argv[] ) {
// create a new instance
Fraction *frac = [[Fraction alloc] init];
// set the values
[frac setNumerator: 1];
[frac setDenominator: 3];
// print it
printf( "The fraction is: " );
[frac print];
printf( "\n" );
// free memory
[frac release];
return 0;
}
#import <objc/Object.h>
int main(){
id obj = [Object alloc];
[obj init];
printf("test objc\n");
return 0;
}
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
/*
__builtin_expect
由于大部分程序员在分支预测方面做得很糟糕,所以GCC提供了这个内建函数来帮助程序员处理分支预测,优化程序。
其第一个参数exp为一个整型表达式,这个内建函数的返回值也是这个exp,而c为一个编译期常量.
这个函数的语义是:你期望exp表达式的值等于常量c,从而GCC为你优化程序,将符合这个条件的分支放在合适的地方。
因为这个程序只提供了整型表达式,所以如果你要优化其他类型的表达式,可以采用指针的形式。
说到底__builtin_expect函数就是为了优化可能性大的分支程序。
if() 语句你照用, 跟以前一样.
只是 如果你觉得if()是1 的可能性非常大的时候,就在表达式的外面加一个likely()
如果可能性非常小(比如几率非常小),就用unlikely()包裹上。
*/
#define likely(x) (__builtin_expect((x) != 0, 1))
#define unlikely(x) (__builtin_expect((x) != 0, 0))
#define SEG_LEN (1024 * 256)
#define MAX_VBUF_LEN 65535
#define INIT_SEG_SIZE 8
typedef struct Tail_Buff
{
int finish;
int n; //从倒数第几行开始看
int last_rs;
int lines; //文件行数
int seg_used;
int seg_size;
long file_size; //文件大小
FILE* f; //文件句柄
char* first_line;//第一行指针
char buf[1];
}Tail_Buff;
static Tail_Buff* tb = NULL;
static void print_usage(char* progname)
{
printf("Usage: %s -n nnnn filename\n", progname);
}
static inline char* get_buf(Tail_Buff* b, int i)
{
printf("get_buf: %d\n",b->buf + i * SEG_LEN);
printf("get_buf buf char %c\n",b->buf + i * SEG_LEN);
return b->buf + i * SEG_LEN;
}
/*
* TODO 查询一下**的意思
*/
static inline int read_lines(Tail_Buff** pb)
{
Tail_Buff* b = *pb;
int len;
printf("\n\n");
printf("read_lines start....\n");
printf("b->seg_size %d\n",b->seg_size);
printf("b->finish %d\n",b->finish);
printf("b->seg_used %d\n",b->seg_used);
printf("sizeof(Tail_Buff): %d\n",sizeof(Tail_Buff));
printf("sizeof(Tail_Buff) + SEG_LEN * b->seg_size): %d\n",(sizeof(Tail_Buff) + SEG_LEN * b->seg_size));
printf("\n\n");
if(unlikely(b->seg_used == b->seg_size))
{
b->seg_size *= 1.6;
/*
realloc函数是一个C语言的库函数,在头文件<stdlib.h>里。先来看看realloc函数的原型。
void *realloc(void *p, size_t size);
realloc函数的作用是把malloc函数动态分配的内存空间的大小作调整。如果是扩大内存分配的话,成功的话还可以保证原来那部分大小的内存不被修改。
如果是减少内存分配的话,成功的话也可以保证调整后的那部分大小的内存跟原来的内容一样。
因为有了这些特点,所以可以使用realloc函数实现动态数组,也就是类似C++的vector的功能,同时底层的内存管理则不需要程序员参与。
使用这个函数,要注意一个地方,就是不能马上用原来的指针保存新的空间。如下面的例子。
p = realloc(p, newsize);
这样的话,万一新分配不成功,返回了NULL,那么原来的内存指针就会丢失。正确的使用方法如下。
tempp = realloc(p, newsize);
if (tempp == NULL) {
}
p = tempp;
先使用一个临时指针保存重新分配的结果,并且检查是否NULL,然后如果没问题再交给原来的指针。
*/
if(!(b = *pb = (Tail_Buff*)realloc(b, sizeof(Tail_Buff) + SEG_LEN * b->seg_size)))
{
fprintf(stderr, "fatal: out of memory\n");
return -1;
}
}
printf("-((b->seg_used + 1) * SEG_LEN): %d\n",-((b->seg_used + 1) * SEG_LEN));
if(unlikely(0 != fseek(b->f, -((b->seg_used + 1) * SEG_LEN), SEEK_END)))
{
fseek(b->f, 0, SEEK_SET);
b->finish = 1;
}
printf("b->seg_size %d\n",b->seg_size);
printf("b->finish %d\n",b->finish);
len = b->file_size - b->seg_used * SEG_LEN;
printf("len is %d\n",len);
len = len > SEG_LEN ? SEG_LEN : len;
printf("len is %d\n",len);
/*
函数名: fread
功 能: 从一个流中读数据
用 法: int fread(void *ptr, int size, int nitems, FILE *stream);
参 数:用于接收数据的地址(字符型指针)(ptr)
单个元素的大小(size)
元素个数(nitems)
提供数据的文件指针(stream)
返回值:成功读取的元素个数
*/
b->last_rs = fread(get_buf(b, b->seg_used), 1, len, b->f);
printf("b->last_rs: %d\n",b->last_rs);
b->seg_used++;
printf("b->seg_used %d\n",b->seg_used);
printf("SEG_LEN %d\n",SEG_LEN);
if(unlikely(SEG_LEN != b->last_rs)) b->finish = 1;
printf("b->finish %d\n",b->finish);
return 0;
}
static inline int count_lines(Tail_Buff* b)
{
/*
凡是声明为register的变量,操作系统都会企图将其放入寄存器中以加快速度.
如果寄存器中已满,则将由计算机硬件将寄存器中最久未使用的变量调入到高速缓冲存储器(Cache)中,同时放入你的变量。
寄存器是CPU的一部分,所以其访问速度会远远高于同内存的访问速度。
*/
register char* s = get_buf(b, b->seg_used - 1), *p = s + b->last_rs - 1;
printf("register char* s: %s\n",s);
while(likely(p-- >= s))
{
if(likely(*p != '\n')) continue;
if(unlikely(++b->lines > b->n))
{
b->first_line = p + 1;
printf("b->first_line: %s\n",b->first_line);
return 1;
}
}
return 0;
}
static inline void print_lines(Tail_Buff* b)
{
int i = 0;
printf("print_lines\n");
printf("MAX_VBUF_LEN: %d\n",MAX_VBUF_LEN);
printf("b->seg_used: %d\n",b->seg_used);
// setvbuf(stdout, NULL, _IOFBF, MAX_VBUF_LEN);
for(i = b->seg_used; i; i--)
{
printf("i: %d\n",i);
const char *ptr, *s = get_buf(b, i - 1);
printf("s: %s\n",s);
size_t len;
printf("tb->seg_used: %d\n",tb->seg_used);
if(likely(i != tb->seg_used))
{
ptr = s, len = SEG_LEN;
}
else
{
ptr = b->first_line ? b->first_line : s;
len = s + b->last_rs - ptr;
}
/*
fwrite的定义是: fwrite(buffer,size,count,fp);
(1)buffer:是一个指针,对fwrite来说,是要输出数据的地址。
(2)size:要写的字节数;
(3)count:要进行写多少个size字节的数据项;
(4)fp:文件型指针。
*/
printf("ptr: %s\n",ptr);
printf("len: %d\n",len);
fwrite(ptr, len, 1, stdout);
}
printf("end printlines\n");
}
int main(int argc, char* argv[]){
FILE *f;
const char* filename;
int rc = 0, n;
long file_size;
if(argc != 4 || argv[1][0] != '-' || argv[1][1] != 'n')
{
print_usage(argv[0]);
return -1;
}
n = atoi(argv[2]);
printf("n=%d\n",n);
if(n < 0) n = 1;
filename = argv[3];
if(!(f = fopen(filename, "r")))
{
fprintf(stderr, "error: open file %s failed, %s\n", filename, strerror(errno));
return -1;
}
/*
【説明】
ファイル fp のファイル位置指示子を origin を基準として、offset バイト移動します。
バイナリストリームでは、origin に SEEK_END を指定した場合には意味どおりに動作するかどうかは不定です。
テキストストリームでは、offset が0であるか、または offset が同じストリームに対する以前の ftell関数の呼出しで返された値でなければなりません。後者の場合、origin は SEEK_SETでなければなりません。
fseek の呼び出し成功で、終了指示子をクリアします。
fseek の呼出しの後では、入力、出力どちらの動作も可能です。
【引数】
FILE *fp   : FILEポインタ
long offset  : 移動バイト数
int origin  : SEEK_SET (ファイルの先頭)
         SEEK_CUR (ファイルの現在位置)
         SEEK_END (ファイルの終端)
【戻り値】
正常時 : =0
異常時 : ≠0
http://www9.plala.or.jp/sgwr-t/lib/fseek.html
*/
fseek(f, 0, SEEK_END);
printf("ファイル位置 = %ld\n",ftell(f));
if(!(file_size = ftell(f)))
{
goto exit_tail1;
}
printf("sizeof(Tail_Buff): %d\n",sizeof(Tail_Buff));
printf("sizeof(Tail_Buff) + SEG_LEN * INIT_SEG_SIZE: %d\n",sizeof(Tail_Buff) + SEG_LEN * INIT_SEG_SIZE);
if(!(tb = (struct Tail_Buff*)malloc(sizeof(Tail_Buff) + SEG_LEN * INIT_SEG_SIZE)))
{
fprintf(stderr, "fatal: out of memory\n");
goto exit_tail1;
}
tb->lines = 0;
tb->file_size = file_size;
tb->first_line = NULL;
tb->n = n;
tb->f = f;
tb->seg_size = INIT_SEG_SIZE;
tb->last_rs = tb->finish = tb->seg_used = 0;
/*
setvbuf函数,则由malloc函数来分配缓冲区。
参数size指明了缓冲区的长度(必须大于0),而参数type则表示了缓冲的类型,其值可以取如下值:
_IOFBF 文件全部缓冲,即缓冲区装满后,才能对文件读写
_IOLBF 文件行缓冲,即缓冲区接收到一个换行符时,才能对文件读写
_IONBF 文件不缓冲,此时忽略buf,size的值,直接读写文件,不再经过文件缓冲区缓冲
http://www9.plala.or.jp/sgwr-t/lib/setvbuf.html
*/
setvbuf(f, NULL, _IONBF, MAX_VBUF_LEN);
while(1)
{
if(read_lines(&tb) < 0) goto exit_tail2;
if(count_lines(tb) || tb->finish) break;
}
print_lines(tb);
exit_tail2:
free(tb);
goto exit_tail;
exit_tail1:
rc = -1;
exit_tail:
fclose(tb->f);
return rc;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment