2 ** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
4 ** This program is free software; you can redistribute it and/or modify
5 ** it under the terms of the GNU Lesser General Public License as published by
6 ** the Free Software Foundation; either version 2.1 of the License, or
7 ** (at your option) any later version.
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ** GNU Lesser General Public License for more details.
14 ** You should have received a copy of the GNU Lesser General Public License
15 ** along with this program; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #define STRINGS_DEBUG 0
30 static void hexdump (void *data
, int len
) ;
34 psf_store_string (SF_PRIVATE
*psf
, int str_type
, const char *str
)
35 { char new_str
[128] ;
36 size_t len_remaining
, str_len
;
40 return SFE_STR_BAD_STRING
;
42 str_len
= strlen (str
) ;
44 /* A few extra checks for write mode. */
45 if (psf
->file
.mode
== SFM_WRITE
|| psf
->file
.mode
== SFM_RDWR
)
46 { if ((psf
->str_flags
& SF_STR_ALLOW_START
) == 0)
47 return SFE_STR_NO_SUPPORT
;
48 if (psf
->have_written
&& (psf
->str_flags
& SF_STR_ALLOW_END
) == 0)
49 return SFE_STR_NO_SUPPORT
;
50 /* Only allow zero length strings for software. */
51 if (str_type
!= SF_STR_SOFTWARE
&& str_len
== 0)
52 return SFE_STR_BAD_STRING
;
55 /* Find the next free slot in table. */
56 for (k
= 0 ; k
< SF_MAX_STRINGS
; k
++)
57 { /* If we find a matching entry clear it. */
58 if (psf
->strings
[k
].type
== str_type
)
59 psf
->strings
[k
].type
= -1 ;
61 if (psf
->strings
[k
].type
== 0)
66 str_flags
= SF_STR_LOCATE_START
;
67 if (psf
->file
.mode
== SFM_RDWR
|| psf
->have_written
)
68 { if ((psf
->str_flags
& SF_STR_ALLOW_END
) == 0)
69 return SFE_STR_NO_ADD_END
;
70 str_flags
= SF_STR_LOCATE_END
;
73 /* More sanity checking. */
74 if (k
>= SF_MAX_STRINGS
)
75 return SFE_STR_MAX_COUNT
;
77 if (k
== 0 && psf
->str_end
!= NULL
)
78 { psf_log_printf (psf
, "SFE_STR_WEIRD : k == 0 && psf->str_end != NULL\n") ;
79 return SFE_STR_WEIRD
;
82 if (k
!= 0 && psf
->str_end
== NULL
)
83 { psf_log_printf (psf
, "SFE_STR_WEIRD : k != 0 && psf->str_end == NULL\n") ;
84 return SFE_STR_WEIRD
;
87 /* Special case for the first string. */
89 psf
->str_end
= psf
->str_storage
;
92 { case SF_STR_SOFTWARE
:
93 /* In write mode, want to append libsndfile-version to string. */
94 if (psf
->file
.mode
== SFM_WRITE
|| psf
->file
.mode
== SFM_RDWR
)
95 { if (strstr (str
, PACKAGE
) == NULL
)
97 ** If the supplied string does not already contain a
98 ** libsndfile-X.Y.Z component, then add it.
100 if (strlen (str
) == 0)
101 snprintf (new_str
, sizeof (new_str
), "%s-%s", PACKAGE
, VERSION
) ;
103 snprintf (new_str
, sizeof (new_str
), "%s (%s-%s)", str
, PACKAGE
, VERSION
) ;
106 snprintf (new_str
, sizeof (new_str
), "%s", str
) ;
113 case SF_STR_COPYRIGHT
:
115 case SF_STR_COMMENT
:
118 case SF_STR_LICENSE
:
119 case SF_STR_TRACKNUMBER
:
124 psf_log_printf (psf
, "%s : SFE_STR_BAD_TYPE\n", __func__
) ;
125 return SFE_STR_BAD_TYPE
;
128 str_len
= strlen (str
) ;
130 len_remaining
= SIGNED_SIZEOF (psf
->str_storage
) - (psf
->str_end
- psf
->str_storage
) ;
132 if (len_remaining
< str_len
+ 2)
133 return SFE_STR_MAX_DATA
;
135 psf
->strings
[k
].type
= str_type
;
136 psf
->strings
[k
].str
= psf
->str_end
;
137 psf
->strings
[k
].flags
= str_flags
;
139 memcpy (psf
->str_end
, str
, str_len
+ 1) ;
140 /* Plus one to catch string terminator. */
141 psf
->str_end
+= str_len
+ 1 ;
143 psf
->str_flags
|= str_flags
;
146 psf_log_printf (psf
, "str_storage : %X\n", (int) psf
->str_storage
) ;
147 psf_log_printf (psf
, "str_end : %X\n", (int) psf
->str_end
) ;
148 psf_log_printf (psf
, "sizeof (str_storage) : %d\n", SIGNED_SIZEOF (psf
->str_storage
)) ;
149 psf_log_printf (psf
, "used : %d\n", (int ) (psf
->str_end
- psf
->str_storage
)) ;
150 psf_log_printf (psf
, "remaining : %d\n", SIGNED_SIZEOF (psf
->str_storage
) - (psf
->str_end
- psf
->str_storage
)) ;
152 hexdump (psf
->str_storage
, 300) ;
156 } /* psf_store_string */
159 psf_set_string (SF_PRIVATE
*psf
, int str_type
, const char *str
)
160 { if (psf
->file
.mode
== SFM_READ
)
161 return SFE_STR_NOT_WRITE
;
163 return psf_store_string (psf
, str_type
, str
) ;
164 } /* psf_set_string */
167 psf_get_string (SF_PRIVATE
*psf
, int str_type
)
170 for (k
= 0 ; k
< SF_MAX_STRINGS
; k
++)
171 if (str_type
== psf
->strings
[k
].type
)
172 return psf
->strings
[k
].str
;
175 } /* psf_get_string */
178 psf_location_string_count (const SF_PRIVATE
* psf
, int location
)
181 for (k
= 0 ; k
< SF_MAX_STRINGS
; k
++)
182 if (psf
->strings
[k
].type
> 0 && psf
->strings
[k
].flags
& location
)
186 } /* psf_location_string_count */
188 /*==============================================================================
195 hexdump (void *data
, int len
)
196 { unsigned char *ptr
;
201 puts ("---------------------------------------------------------") ;
203 { for (k
= 0 ; k
< 16 ; k
++)
204 printf ("%02X ", ptr
[k
] & 0xFF) ;
206 for (k
= 0 ; k
< 16 ; k
++)
207 printf ("%c", psf_isprint (ptr
[k
]) ? ptr
[k
] : '.') ;