1 /*
2 	Audio File Library
3 	Copyright (C) 1998, Michael Pruett <michael@68k.org>
4 
5 	This library is free software; you can redistribute it and/or
6 	modify it under the terms of the GNU Lesser General Public
7 	License as published by the Free Software Foundation; either
8 	version 2.1 of the License, or (at your option) any later version.
9 
10 	This library is distributed in the hope that it will be useful,
11 	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 	Lesser General Public License for more details.
14 
15 	You should have received a copy of the GNU Lesser General Public
16 	License along with this library; if not, write to the
17 	Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 	Boston, MA  02110-1301  USA
19 */
20 
21 /*
22 	Miscellaneous.cpp
23 
24 	This file contains routines for dealing with the Audio File
25 	Library's internal miscellaneous data types.
26 */
27 
28 #include "config.h"
29 
30 #include <algorithm>
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include "FileHandle.h"
36 #include "Setup.h"
37 #include "afinternal.h"
38 #include "audiofile.h"
39 #include "util.h"
40 
afInitMiscIDs(AFfilesetup setup,const int * ids,int nids)41 void afInitMiscIDs (AFfilesetup setup, const int *ids, int nids)
42 {
43 	if (!_af_filesetup_ok(setup))
44 		return;
45 
46 	if (setup->miscellaneous != NULL)
47 	{
48 		free(setup->miscellaneous);
49 	}
50 
51 	setup->miscellaneousCount = nids;
52 
53 	if (nids == 0)
54 		setup->miscellaneous = NULL;
55 	else
56 	{
57 		setup->miscellaneous = (MiscellaneousSetup *) _af_calloc(nids,
58 			sizeof (MiscellaneousSetup));
59 
60 		if (setup->miscellaneous == NULL)
61 			return;
62 
63 		for (int i=0; i<nids; i++)
64 		{
65 			setup->miscellaneous[i].id = ids[i];
66 			setup->miscellaneous[i].type = 0;
67 			setup->miscellaneous[i].size = 0;
68 		}
69 	}
70 
71 	setup->miscellaneousSet = true;
72 }
73 
afGetMiscIDs(AFfilehandle file,int * ids)74 int afGetMiscIDs (AFfilehandle file, int *ids)
75 {
76 	if (!_af_filehandle_ok(file))
77 		return -1;
78 
79 	if (ids != NULL)
80 	{
81 		for (int i=0; i<file->m_miscellaneousCount; i++)
82 		{
83 			ids[i] = file->m_miscellaneous[i].id;
84 		}
85 	}
86 
87 	return file->m_miscellaneousCount;
88 }
89 
afInitMiscType(AFfilesetup setup,int miscellaneousid,int type)90 void afInitMiscType (AFfilesetup setup, int miscellaneousid, int type)
91 {
92 	if (!_af_filesetup_ok(setup))
93 		return;
94 
95 	MiscellaneousSetup *miscellaneous = setup->getMiscellaneous(miscellaneousid);
96 	if (miscellaneous)
97 		miscellaneous->type = type;
98 }
99 
afGetMiscType(AFfilehandle file,int miscellaneousid)100 int afGetMiscType (AFfilehandle file, int miscellaneousid)
101 {
102 	if (!_af_filehandle_ok(file))
103 		return -1;
104 
105 	Miscellaneous *miscellaneous = file->getMiscellaneous(miscellaneousid);
106 	if (miscellaneous)
107 		return miscellaneous->type;
108 	return -1;
109 }
110 
afInitMiscSize(AFfilesetup setup,int miscellaneousid,int size)111 void afInitMiscSize (AFfilesetup setup, int miscellaneousid, int size)
112 {
113 	if (!_af_filesetup_ok(setup))
114 		return;
115 
116 	MiscellaneousSetup *miscellaneous = setup->getMiscellaneous(miscellaneousid);
117 	if (miscellaneous)
118 		miscellaneous->size = size;
119 }
120 
afGetMiscSize(AFfilehandle file,int miscellaneousid)121 int afGetMiscSize (AFfilehandle file, int miscellaneousid)
122 {
123 	if (!_af_filehandle_ok(file))
124 		return -1;
125 
126 	Miscellaneous *miscellaneous = file->getMiscellaneous(miscellaneousid);
127 	if (miscellaneous)
128 		return miscellaneous->size;
129 	return -1;
130 }
131 
afWriteMisc(AFfilehandle file,int miscellaneousid,const void * buf,int bytes)132 int afWriteMisc (AFfilehandle file, int miscellaneousid, const void *buf, int bytes)
133 {
134 	if (!_af_filehandle_ok(file))
135 		return -1;
136 
137 	if (!file->checkCanWrite())
138 		return -1;
139 
140 	Miscellaneous *miscellaneous = file->getMiscellaneous(miscellaneousid);
141 	if (!miscellaneous)
142 		return -1;
143 
144 	if (bytes <= 0)
145 	{
146 		_af_error(AF_BAD_MISCSIZE, "invalid size (%d) for miscellaneous chunk", bytes);
147 		return -1;
148 	}
149 
150 	if (miscellaneous->buffer == NULL && miscellaneous->size != 0)
151 	{
152 		miscellaneous->buffer = _af_malloc(miscellaneous->size);
153 		if (miscellaneous->buffer == NULL)
154 			return -1;
155 		memset(miscellaneous->buffer, 0, miscellaneous->size);
156 	}
157 
158 	int localsize = std::min(bytes,
159 		miscellaneous->size - miscellaneous->position);
160 	memcpy((char *) miscellaneous->buffer + miscellaneous->position,
161 		buf, localsize);
162 	miscellaneous->position += localsize;
163 	return localsize;
164 }
165 
afReadMisc(AFfilehandle file,int miscellaneousid,void * buf,int bytes)166 int afReadMisc (AFfilehandle file, int miscellaneousid, void *buf, int bytes)
167 {
168 	if (!_af_filehandle_ok(file))
169 		return -1;
170 
171 	if (!file->checkCanRead())
172 		return -1;
173 
174 	Miscellaneous *miscellaneous = file->getMiscellaneous(miscellaneousid);
175 	if (!miscellaneous)
176 		return -1;
177 
178 	if (bytes <= 0)
179 	{
180 		_af_error(AF_BAD_MISCSIZE, "invalid size (%d) for miscellaneous chunk", bytes);
181 		return -1;
182 	}
183 
184 	int localsize = std::min(bytes,
185 		miscellaneous->size - miscellaneous->position);
186 	memcpy(buf, (char *) miscellaneous->buffer + miscellaneous->position,
187 		localsize);
188 	miscellaneous->position += localsize;
189 	return localsize;
190 }
191 
afSeekMisc(AFfilehandle file,int miscellaneousid,int offset)192 int afSeekMisc (AFfilehandle file, int miscellaneousid, int offset)
193 {
194 	if (!_af_filehandle_ok(file))
195 		return -1;
196 
197 	Miscellaneous *miscellaneous = file->getMiscellaneous(miscellaneousid);
198 	if (!miscellaneous)
199 		return -1;
200 
201 	if (offset >= miscellaneous->size)
202 	{
203 		_af_error(AF_BAD_MISCSEEK,
204 			"offset %d too big for miscellaneous chunk %d "
205 			"(%d data bytes)",
206 			offset, miscellaneousid, miscellaneous->size);
207 		return -1;
208 	}
209 
210 	miscellaneous->position = offset;
211 
212 	return offset;
213 }
214