. 텍스트 입출력

ApiEdit는 파일로부터 읽은 텍스트를 buf 멤버가 가리키는 버퍼에 저장한다. 파일 입출력 대상은 바로 이 buf가 가리키는 메모리이며 buf의 내용을 파일에 쓰는 것이 저장하는 것이고 파일을 읽어 buf에 복사하면 이 파일을 읽어오는 것이다. 이 멤버를 직접 액세스하면 간단하게 파일 입출력을 구현할 수 있다. 그러나 이 멤버는 private 속성을 가지는 철저하게 보호된 멤버여야 하며 호스트에서 직접 이 멤버를 액세스하도록 내버려 두어서는 안된다.

호스트에서 안전하게 사용한다면 문제가 없지만 만에 하나라도 buf[1234]=0 같은 대입문을 실행한다거나 buf[-34]=S처럼 엉뚱한 위치를 액세스하게 되면 아주 위험하다. 고의로 그럴 리야 없겠지만 실수나 에러로 인해 이런 문장이 실행될 수도 있으므로 ApiEdit는 이런 위험에 대해 충분히 방어적인 태세를 갖출 필요가 있다. 그래서 buf는 철저하게 숨기고 이 멤버에 텍스트를 입출력할 수 있는 함수를 제공한다. 다음 세 멤버함수를 추가한다.

 

class CApiEdit

{

     ....

     void SetText(TCHAR *TextBuf);

     void GetText(TCHAR *TextBuf, int BufSize);

     int GetTextLength();

 

버퍼에 텍스트를 읽고 쓰는 GetText, SetText 함수 외에도 문서 길이를 조사하는 GetTextLength 함수가 필요하다. 왜냐하면 호스트가 문서 내용을 읽기 전에 버퍼를 미리 할당해야 하는데 버퍼의 길이를 알아야 필요한 만큼 메모리를 할당할 수 있기 때문이다. 이 함수들의 코드는 다음과 같다.

 

void CApiEdit::SetText(TCHAR *TextBuf)

{

     InitDoc();

     Insert(0,TextBuf);

}

 

void CApiEdit::GetText(TCHAR *TextBuf, int BufSize)

{

     lstrcpyn(TextBuf,buf,BufSize);

}

 

int CApiEdit::GetTextLength()

{

     return doclen;

}

 

문서 길이는 doclen 변수로 간단하게 조사할 수 있으므로 GetTextLength 함수는 이 변수값만 리턴하면 된다. SetText 함수는 InitDoc 함수를 호출하여 문서를 초기화하고 문서 처음인 오프셋 0에서 Insert 함수를 호출하여 전달받은 텍스트를 삽입한다. lstrcpy(buf,TextBuf) 코드로 바로 복사해서는 안되며 반드시 삽입해야 한다. 왜냐하면 Insert 함수는 버퍼에 문자열을 복사하는 작업 외에도 버퍼 길이를 관리하는 아주 중요한 일을 하기 때문이다. Insert 함수를 호출하면 TextBuf의 길이가 얼마인가에 상관없이 buf 크기가 따라서 늘어나므로 아무리 큰 파일이라도 읽을 수 있다.

GetText 함수는 buf의 문자열을 TextBuf로 복사하되 BufSize 이상을 넘지 않도록 한다. 호출측에서는 GetTextLength 함수로 문서 길이를 구하고 이 길이에 널 종료문자의 길이를 더한 만큼 버퍼를 할당한 후 이 함수를 호출해야 한다. lstrcpyn 함수는 최대 BufSize-1개의 문자만을 복사하며 끝에 널 종료문자를 붙여준다는 특징을 잘 간파해야 한다.