이 심하게 소개 편집. 내 문제는 '파일'이라는 개념이 질문에 사용되는 방식에서 비롯된다. 질문은 디스크, 프로그램 및 트랙이 모두 하나의 '파일'에 저장된다는 것을 의미합니다. 저는 질문자가 자신의 파일 시스템을 구축하고 있다고 생각했습니다.이 파일 시스템은이 모든 것을 하나의 파일 구조로 만들었지 만 지금은 그렇게하지 않을 것이라고 결정했습니다. 따라서 기존 파일 시스템 (아마도 표준 파일 시스템)을 사용한다는 가정을 기반으로 실제 답변을 제공하고 그의 전체 데이터 구조가 해당 파일 시스템 내의 하나의 파일에 저장됩니다. 내가 잘못 추측한다면 틀림없이 나는 시정 될 것이다.
먼저 이런 상황에 대한 일반적인 조언을 한 가지 제공합니다. API 사용자의 관점에서 먼저 살펴보십시오. 그런 다음 작성하는 코드가 도메인에서 올바르게 작동하는 세부 사항을 처리 할 필요없이 쉽게 흐르도록 API를 디자인하십시오.
API 디자인을 작업하는 한 가지 방법은 먼저 일부 사용자 코드를 작성하고 API를 작성하여 해당 코드를 작성하기 쉽도록하는 것입니다. 보너스로 API를 실제로 구현 한 후에는 테스트 코드를 사용하여 테스트 해 볼 수 있습니다.
더 구체적인 조언으로 이동;
다음은 시스템에서 세 가지 데이터 유형의 카탈로그입니다. 우리는 당신이 typdef'ed struct (DISC, PROGRAM, TRACK say)를 좋아하고 각각을 표현하기 위해 추상적 인 데이터 타입 또는 'Objects'로 취급 할 수 있습니다.
disc = a collection of programs stored in a file
+-----------+
|file |
+-----------+
|program |
+-----------+
|program |
+-----------+
|... |
+-----------+
|program |
+-----------+
program = a collection of tracks
+-----------+
|ptr->disc |
+-----------+
|name |
+-----------+
|file offset|
+-----------+
|track |
+-----------+
|track |
+-----------+
|... |
+-----------+
|track |
+-----------+
track = a collection of audio samples
+------------------+
|ptr->program |
+------------------+
|name |
+------------------+
|file offset+length|
+------------------+
|file offset+length|
+------------------+
|... |
+------------------+
|file offset+length|
+------------------+
당신이 사용자가 구조에서 데이터를 선택하지 않는 것을 제안한다. C로 구조의 내부를 숨길 수는 없지만 (캐스팅 등으로 농구대를 뛰어 넘지 않고) 추상적 인 유형의 내용에 액세스하지 않고도 사용자가해야 할 일을 할 수있는 기능을 제공 할 수 있습니다 그들 자신. 예를 들어, 우리 가족은 다음과 같이 보일 수 있습니다.
// DISC functions
DISC *dopen( const char *disc_name);
void dstats(int *ptr_nbr_programs, FILE **ptr_file);
void dclose(DISC *disc);
// PROGRAM functions
PROGRAM *popen_name(DISC *disc, const char *program_name);
PROGRAM *popen_idx (DISC *disc, int program_idx);
void pstats(int *ptr_nbr_tracks);
void pclose(PROGRAM *program);
// TRACK functions
TRACK *topen_name(PROGRAM *program, const char *track_name);
TRACK *topen_idx (PROGRAM *program, int track_idx);
int tread(unsigned char *buf, int nbytes_to_read);
void tseek(unsigned long offset);
void tclose(TRACK *track);
이
모든 합리적으로 자기 explanantory해야한다 - 그것은 기존의 표준 C 파일 패러다임을 모델로한다.
먼저 사용자는 dopen()으로 DISC에 대한 ptr을 얻습니다. 이것이 작동한다고 가정하면 (그렇지 않으면 NULL을 리턴 할 것입니다), 그는 dstats()로 모든 전역 DISC 정보를 얻을 수 있습니다. 더 많은 요점으로 그는 popen() 패밀리 함수 중 하나를 가지고 DISC 내의 PROGAM에 ptr을 얻을 수 있습니다.
PROGRAM에 대한 ptr을 사용하여 그는 더 자세히 드릴 다운하여 topen() 패밀리 중 하나를 사용하여 단일 TRACK을 얻을 수 있습니다.
중요한 점은 사용자가 트랙에서 데이터를 가져 오기 위해 오디오 조각을 반복적으로 반복하지 않도록한다는 것입니다. 사용자는 샘플을 읽는 버퍼를 제공하고, 그 버퍼를 채우기 위해 조각을 통해 필요한만큼 반복합니다. tseek() 함수는 임의 액세스를 제공하기 위해 제공됩니다.
모든 매개 변수의 세부 사항을 처리하고 오류를 처리하는 방법을 시도하지는 않았지만 지금은 세련된 개념을 제시하고 있습니다.
전체적으로 '샌드위치'패러다임이 사용됨에 유의하십시오. 입문 '공개'와 종결 '닫기'샌드위치 모든 유형의 작업.
* facepalm * Thanks Charlie – Draemon