2011년 4월 27일 수요일

Avro

: 이기종 간 데이터 타입을 교환할 수 있는 체계를 제공하는 프레임워크.
데이터 직렬화(Serialization)를 기본 개념으로해 RPC호출을 이기종간에 가능하게 하는 개념.
JSON기반의 문장열을 이용해 데이터 타입에 대한 정보를 클라이언트와 서버 사이에 주고 받으면서 데이터 타입을 확인하는 과정을 거치는 형태를 사용한다.
이런방식을 이용하면 컴파일 시점이 아닌 실행 시점에서 IDL정보를 이용해 호추하는 방식도 지원할 수 있다.

1. 스키마
- 전송이나 저장시의 데이터 포맷에 대한 정의.
RPC 호출 : 전송할 데이터의 스키마 정보를 먼저 전송한 후 실제 데이터 전송.
파일저장 : 파일 앞부분에 스키마 정보 저장, JSON형태로 표현된다.

예) {"type":"타입명" ...속성...} 형식으로 정의. 사용 예{"type":"string"}
type은 예약어로 스키마 정의를 나타낸다.
type명의 두가지 종류.
1. 원시타입(Primitive type)
- 종류



  • null : 값 없음

  • boolean : true, false

  • int : 32비트 부호있는 정수

  • long : 64비트 부호있는 정수

  • float : 단일 정확도(32비트) IEEE 754부동 소수점

  • double : 이중 정확도(63비트) IEEE754 부동 소수점

  • bytes : 바이트 배열

  • string : 유니코드 문자열
2. 복합타입(Complex type)


  • 레코드 (record)

  • 열거형 (enum)

  • 배열 (array)

  • 맵 (map)

  • 유니온 (union)

  • 고정 길이 (fixed)
- 3가지 속성을 가지고 다음과 같다.
name : 레코드의 이름(클래스명 또는 구조체명)
doc : 스키마에대한 설명으로 필수항목은 아님
fields :여러 개의 필드를 정의. 필드는 name, doc, type, default 속성을 가진다.

2. 복합 타입
3. 객체 컨테이너 파일
4. 프로토콜
: RPC호출을 위한 프로토콜이다. RPC호출을 위해서 프로시저에 대한 인터페이스 정의와 송수신되는 데이터에 대한 타입정의가 필요하다. 프로토콜정의는 스키마와 동일하게 JSON포맷으로 정의한다. 속성은 아래와 같다.


  • protocol : 프로코콜의 이름, 코드로 생성됐을 때 인터페이스명에 해당한다.

  • namespace : 네임스페이스를 한정할 수 있는 문자열로, 코드로 생성됐을때 패키지에 해당한다(선택항목)

  • doc : 프로토콜에 대한 설명(선택항목)

  • types : 프로토콜에서 사용하는 타입을 정의한다. 스키마에 설명한 복합 타입중 레코드, 열거형 고정 길이형이 사용되면, 추가로 에러 타입을 정의할 수 있다. 에러타입과 동일하지만 타입을 나타내는 키워드로 'error'를 사용한다. types는 선택 항목이며 쓰리프트의 'struct'에 대응하는 개념이다.

  • messages : RPC메소드를 정의한다. 하나의 프로토몰 내에서는 여러 개의 메시지를 정의할 수 있다. 메시지는 쓰리프트의 'service'에 대응하는 개념이며 각 메시지는 이름과 'doc'메시지에 대한 설명, 'request' : 입력 파라미터 목록으로 'name', 'type'속성을 가진다., 'response'반환 타입을 정의한다., 'errors'예외타입 목록을 정의한다.

2010년 10월 15일 금요일

ViewGroup 모서리 둥글게 둥글게

ViewGroup 모서리 둥글게

 

res -> drawable ->radius.xml

<?xml version="1.0" encoding="UTF-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#99FFFFFF"/>

    <corners android:radius="15dip"/>

    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" /> 

</shape>



main.xml


<TableLayout android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:background="@drawable/com_rounded_corner"

android:padding="10dip"

android:orientation="vertical">

...

</TableLayout>


출처 : http://lomohome.com/317

2010년 1월 30일 토요일

C로 개발을 할땐...

1. 컴파일시 -Wall 옵션을 사용하여 최대한 상세한 컴파일 정보를 참조하면서 개발하라.
   
gcc test.c test -o dump -Wall

2. 외부 변수 참조시 외부 전역변수대신 static으로 선언하고, 변수값을 읽는 전용함수를 사용하라.
static int value    // 내부적으로 쓸 외부값을 받을 변수

// 값을 가져 온다.
int get_value()  
{
   return (value);
}  

// 값을 셋팅 한다.
int set_value(int new_value)  
{
   return (value = new_value);
}


2010년 1월 29일 금요일

가변인수 : stdarg.h

1. 생략기호를 사용하는 함수 원형을 제공한다. ( ...을 사용한다는 말이다.)
2. 함수 정의에서 va_list형 변수를 만든다.
3. 인수 리스트에 대한 변수를 초기화하기 위해서 매크로를 사용한다.
4. 인수 리스트에 접근하는데 매크로를 이용한다.
5. 지우기 위해 매크로를 이용한다.

void f1(int n, ...);    // 유효
int f2(int n, const char *s, ...);   //유효
char f3(char 1, ..., char c2);  //무효
double f3();   // 무효

첫번째 선언의 맨오른쪽 인수인 "..."은 표준 명칭으로 parmN 이라고 한다.
parmN은 첫째는 n이 되고, 두번째는 s가 된다. 다음과 같이 사용될 수 있다.

f1(2, 200, 400);          // 2개의 추가 인수
f(4, 13, 117, 18, 23);  // 4개의 추가 인수

인수의 맨앞 숫자는 뒤 따라올 인수들의 수를 나타낸다.

double sum(int lim,...)
{
   va_list ap;               // 생략된 인수를 담을 객체를 선언한다.
   ...
}

stdargs.h에 선언된 va_start()매크로를 사용해서 선언된 va_list변수에 인수 리스트를 복사한다.

va_start(ap, lim);   // 인수 리스트에 대한 ap를 초기화

다음으로 넘겨준 인수를 가져와야 할 것이다. 그래야 지지고 볶고 할것 아닌가..
va_arg()를 사용하여 데이터에 엑세스 한다.

int toc;
double tic;
tic = va_arg(ap, double);
toc = va_arg(ap, int)

인수의 형식은 va_arg()의 두번째 인수인 규격에 정확히 맞아야 한다.

마지막으로 리스트 선언된 객체를 지운다

va_end(ap);    // 해제

인수를 해제하기전 데이터를 백업 받아야 한다면 다음 매크로를 사용하면된다.

//arg_copy();
va_list ap;
va_list apcopy;
double
double tic;
int toc;
...
va_start(ap, lim);             // 인수 리스트로 ap를 초기화한다.
va_copy(apcopy, ap);        // ap를 ap copy에 복사한다.
tic = va_arg(a, double);    // 첫 번째 인수를 검색한다.
toc = va_arg(ap, int);       // 두 번째 인수를 검색한다.

  1 #include <stdio.h>
  2 #include <stdarg.h>
  3 double sum(int, ...);
  4
  5 int main(void)
  6 {
  7    double s, t;
  8    s = sum(3,1.1,2.2,3.3);
  9    t = sum(6,1.1,2.1,3.1,4.1,5.1,6.1);
 10    printf("%g %g\n", s, t);
 11    return 0;
 12 }
 13
 14 double sum(int lim, ...)
 15 {
 16    va_list ap;
 17    double tot = 0;
 18    int i;
 19    va_start(ap, lim);
 20    for(i=0;i<lim;i++)
 21       tot += va_arg(ap, double);
 22    va_end(ap);
 23    return tot;
 24 }

va_arg는 별도의 카운터를 하지 않아도 다음 값을 가져오는 걸로 확인되었다.

memcpy(), memmove()

하나의 배열은 다른 배열에 할당할 수 없으므로 하나의 배열을 한 요소씩 다른 배열에 복사하는 루프를 사용해 왔다. 문자 배열의 경우 한 가지 예외가 있다면  ctrcpy()와 strncpy() 함수를 이용해 왔다는 것이다 memcpy()와 memmove()함수는 다른 좀류의 배열에 대해서도 편리를 제공한다. 두함 수에 대한 원현은 다음과 같다.

void * memcpy(void *restrict s1, const void *restric s2, size_t n);
void * memmove(void *s1, const oid *s2, size_t n);

두 함수 모두 s2에 의해 포인트된 위치에서 s1에 포인트된 위치로 n바이트를 복사하여 s1값으로 봔환한다. 키워드 restrict(코드 최적화)로 나타나듯이, 이 두 함수의 다른 점은 memcpy()는 두개의 메모리 범위간의 중복이 없다고 가정할 수 있다는 것이다. memmove()함수는 그런 전제를 하지 않으므로 모든 바이트가 마지막 수신지에 복사되기 전에 임시 버퍼에 먼저 복사되는 것처럼 복사가 이루어진다. 만약 중복되는 범위가 있을때 memcpy()함수를 사용한다면 어떻게 될 것인가? 이 행위는 정의 되지 않는다. 즉, 실핼할 수도 있고 안 할 수도 있다는 뜻이다. 컴파일러는 memcpy()함수를 사용하지 말아야 할 때 사용하게 되면 그것을 멈출 수 없다. 따라서, 사용시 범위가 중복되지 않도록 확인하는 것은 사용자의 책임이다. 이것이 바로 프로그래머에게는 또하나의 부담이 될것이다.

이러한 함수들은 모든 데이터형과 작동하도록 설계되어 있기 때문에, 두개의 포인터 인수는 void형 포이터이다. C는 void *의 포인터에 어떤 포인터 형식도 할당할 수 있도록 해준다. 그러나 이 폭넓은 수용은 이러한 함수들이 어떤 종류의 데이터가 복사되는지 알지 못한다는 단점이 있다. 그러므로 이런 함수들은 복사될 바이트 수를 나타내기 위해 세 번째 인수를 사용한다. 일반적으로 배열의 경우, 바이트 수는 요소의 수가 아니라는 것을 주의한다. 따라서 10 double값의 배열을 복사했다면 세 번째 인수로 10이 아닌 10*sizeof(double)를  사용해야 할 것이다.


  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #define SIZE 10
  5
  6 void show_array(const int ar[], int n);
  7
  8 int main(void)
  9 {
 10    int values[SIZE] = {1,2,3,4,5,6,7,8,9,10};
 11    int target[SIZE];
 12    double curious[SIZE / 2] = {1.0, 2.0, 3.0, 4.0, 5.0};
 13    int * pi;
 14
 15    memcpy(target, values, SIZE * sizeof(int));
 16    puts("target:");
 17    show_array(target, SIZE);
 18    pi = (int *)malloc(SIZE * sizeof(int));
 19    memcpy(pi, values, SIZE * sizeof(int));
 20    puts("pi:");
 21    show_array(pi, SIZE);
 22    memmove(values + 2, values, 5);
 23    puts("values");
 24    show_array(values, SIZE);
 25    memcpy(target,curious, (SIZE /2) * sizeof(double));
 26    puts("target:");
 27    show_array(target, SIZE);
 28
 29    return 0;
 30 }
 31
 32 void show_array(const int ar[], int n)
 33 {
 34    int i;
 35    for(i = 0; i < n; i++)
 36       printf("%d ", ar[i]);
 37    putchar('\n');
 38 }
결과
target:
1 2 3 4 5 6 7 8 9 10
pi:
1 2 3 4 5 6 7 8 9 10
values
1 2 1 2 5 6 7 8 9 10
target:
0 1072693248 0 1073741824 0 1074266112 0 1074790400 0 1075052544

memcpy()에 대한 마지막 호출은 double형에서 int형 배열까지의 데이터를 복사한다. 이것은 memcpy()가 데이터형을 알지 모사며 그것에 대해 상관하지도 않는다는 것을 본여준다. 즉, 하나의 위치에서 다른 위치로 바이트를 복사할 뿐이다(예를들어, 구조체에서 문자 배열로 바이트를 복사할 수 있다.) 데이터 변환 또한 없다. 요소마다 지정하는 루프를 가지면 할당하는 동안 double형 값은 int형으로 변환될지도 모른다. 이경우에 프로그램은 바이트를 있는 그대로를 복사한 다음 그것이 int형인 것처럼 비트 패턴을 번역한다.














디버깅에는 assert()!!!

assert.h헤더파일이 지원하는 assert라이브러리는 디버깅 프로그램을 지원하는 작은 라이브러리이다. 인수는 정수식 표현을 나타낸다. assert()매크로는 표준 오류 스트림(stderr)에 오류 메시지를 작성하고, 프로그램을 종료하는 abort() 함수를 호출한다. abort()함수는 stdlib.h 헤더에 선언된다.
다음 예제를 보자
#include <stdio.h>
#include <math.h>
#include <assert.h>

int main()
{
   double x, y, z;
   puts("Enter a pair of numbers (0 0 to quit): ");
   while(scanf("%lf%lf", &x, &y) == 2 && (x != 0 || y != 0))
   {
      z = x * x - y * y;
      assert(z >= 0);
      printf("Answer is %f\n", sqrt(z));
      puts("Next pair of numbers: ");
   }
   return 0;
}

결과
Enter a pair of numbers (0 0 to quit):
4 3
Answer is 2.645751
Next pair of numbers:
5 3
Answer is 4.000000
Next pair of numbers:
3 5
assert: assert.c:12: main: Assertion `z >= 0' failed.

일반적으로 인수는 관계식이거나 논리식이다. assert()가 프로그램을 강제로 중지시키면, 먼저 실패한 테스트를 출력하고, 다음으로 테스트를 포함하는 파일명, 라인 번호를 표시나다. 관계식이 false가되면 해당 코드와 경로 및 파일명, 그리고 라인번호를 같이출력한다.
더 멋진 장점은 선언부분에  아래의 정의를 추가한다.

#define NDEBUG


위 의 선언을 정의하면 모든 asert()함수가 비활성화 된다. 당연히 디버깅이 더 필요할시에는 주석처리하고 다시 컴파일 하면 된다. 디버깅용으로 아주 좋을 것이다.