더북(TheBook)

스트림에 데이터를 보내려면 주로 write(const void* inData, size_t inByteCount)를 사용한다. Write()에는 여러 오버로드(overload) 형태가 있는데 이들을 쓰면 바이트 개수를 일일이 파라미터로 지정하지 않아도 된다. 좀 더 완성된 구현을 위해선 Write()를 템플릿으로 만들어 모든 자료형을 처리하게 할 수도 있는데, 이때 원시 자료형이 아닌 것은 직렬화하지 않도록 해야 한다. 원시 자료형이 아닐 경우 직렬화에 특수 처리가 필요함을 명심하자. 템플릿 Write()를 안전하게 작성하려면 자료형 특성 정보(type traits)를 이용한 정적 단언문을 쓰는 것도 한 방법이다.

template<typename T> void Write(const T& inData)
{
    // 원시 자료형인지 여부를 컴파일 타임에 검사
    static_assert(
        std::is_arithmetic<T>::value ||
        std::is_enum<T>::value,
        "Generic Write only supports primitive data types");
    
    Write(&inData, sizeof(inData));
}

어떤 방식이건 보조 함수를 만들어 자동으로 바이트 개수를 세어주도록 하면 사용자가 자료형의 바이트 개수를 잘못 넘겨서 발생할 오류를 줄이는 데 도움이 된다.

데이터를 기록하는 도중 mBuffer의 용량이 모자라게 되는 경우, 버퍼가 두 배 또는 기록에 필요한 만큼 확장된다. 이는 흔한 메모리 확장 기법으로, 몇 배수로 확장할지는 필요한 목적에 따라 달리한다.

warning!

GetBufferPtr() 함수가 제공되어 스트림의 내부 버퍼의 포인트에 접근할 수 있지만, 이 버퍼의 소유권은 스트림이 갖고 있으니 주의하자. 다시 말해 스트림이 해제되면 이 포인터도 무효가 된다. 스트림을 해제하고 난 뒤에도 버퍼 포인터를 유지하고 싶다면 버퍼를 std::shared_ptr<std::vector<uint8_t>>로 구현하면 된다. 이는 이 장 마지막의 연습 문제로 남겨 두겠다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.