123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- /* MelderFile.cpp
- *
- * Copyright (C) 1992-2018 Paul Boersma
- *
- * This code is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This code is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this work. If not, see <http://www.gnu.org/licenses/>.
- */
- #include "melder.h"
- #include "../kar/UnicodeData.h"
- extern "C" int FLAC__stream_encoder_finish (FLAC__StreamEncoder *);
- extern "C" void FLAC__stream_encoder_delete (FLAC__StreamEncoder *);
- /*
- * Functions for wrapping the file pointers.
- */
- MelderFile MelderFile_open (MelderFile me) {
- my filePointer = Melder_fopen (me, "rb");
- my openForReading = true;
- return me;
- }
- char * MelderFile_readLine (MelderFile me) {
- if (! my filePointer)
- return nullptr;
- if (feof (my filePointer))
- return nullptr;
- static char *buffer;
- static integer capacity;
- if (! buffer) {
- buffer = Melder_malloc (char, capacity = 100);
- }
- integer i = 0;
- for (; true; i ++) {
- if (i >= capacity) {
- buffer = (char *) Melder_realloc (buffer, capacity *= 2);
- }
- int c = fgetc (my filePointer);
- if (feof (my filePointer))
- break;
- if (c == '\n') {
- c = fgetc (my filePointer);
- if (feof (my filePointer)) break; // ignore last empty line (Unix)
- ungetc (c, my filePointer);
- break; // Unix line separator
- }
- if (c == '\r') {
- c = fgetc (my filePointer);
- if (feof (my filePointer)) break; // ignore last empty line (Macintosh)
- if (c == '\n') {
- c = fgetc (my filePointer);
- if (feof (my filePointer)) break; // ignore last empty line (Windows)
- ungetc (c, my filePointer);
- break; // Windows line separator
- }
- ungetc (c, my filePointer);
- break; // Macintosh line separator
- }
- buffer [i] = c;
- }
- buffer [i] = '\0';
- return buffer;
- }
- MelderFile MelderFile_create (MelderFile me) {
- my filePointer = Melder_fopen (me, "wb");
- my openForWriting = true; // a bit superfluous (will have been set by Melder_fopen)
- return me;
- }
- void MelderFile_write (MelderFile file, conststring32 string) {
- if (! file -> filePointer)
- return;
- if (! string)
- return;
- int64 length = str32len (string);
- FILE *f = file -> filePointer;
- if (file -> outputEncoding == kMelder_textOutputEncoding_ASCII || file -> outputEncoding == kMelder_textOutputEncoding_ISO_LATIN1) {
- for (int64 i = 0; i < length; i ++) {
- char kar = (char) (char8) string [i]; // truncate
- if (kar == '\n' && file -> requiresCRLF)
- putc (13, f);
- putc (kar, f);
- }
- } else if (file -> outputEncoding == (unsigned long) kMelder_textOutputEncoding::UTF8) {
- for (int64 i = 0; i < length; i ++) {
- char32 kar = string [i];
- if (kar <= 0x00'007F) {
- if (kar == U'\n' && file -> requiresCRLF)
- putc (13, f);
- putc ((int) kar, f); // guarded conversion down
- } else if (kar <= 0x00'07FF) {
- putc (0xC0 | (kar >> 6), f);
- putc (0x80 | (kar & 0x00'003F), f);
- } else if (kar <= 0x00'FFFF) {
- putc (0xE0 | (kar >> 12), f);
- putc (0x80 | ((kar >> 6) & 0x00'003F), f);
- putc (0x80 | (kar & 0x00'003F), f);
- } else {
- putc (0xF0 | (kar >> 18), f);
- putc (0x80 | ((kar >> 12) & 0x00'003F), f);
- putc (0x80 | ((kar >> 6) & 0x00'003F), f);
- putc (0x80 | (kar & 0x00'003F), f);
- }
- }
- } else {
- for (int64 i = 0; i < length; i ++) {
- char32 kar = string [i];
- if (kar == U'\n' && file -> requiresCRLF)
- binputu16 (13, f);
- if (kar <= 0x00'FFFF) {
- binputu16 ((char16) kar, f);
- } else if (kar <= 0x10'FFFF) {
- kar -= 0x01'0000;
- binputu16 (0xD800 | (char16) (kar >> 10), f);
- binputu16 (0xDC00 | (char16) ((char16) kar & 0x03ff), f);
- } else {
- binputu16 (UNICODE_REPLACEMENT_CHARACTER, f);
- }
- }
- }
- }
- void MelderFile_writeCharacter (MelderFile file, char32 kar) {
- FILE *f = file -> filePointer;
- if (! f)
- return;
- if (file -> outputEncoding == kMelder_textOutputEncoding_ASCII || file -> outputEncoding == kMelder_textOutputEncoding_ISO_LATIN1) {
- if (kar == U'\n' && file -> requiresCRLF)
- putc (13, f);
- putc ((int) kar, f);
- } else if (file -> outputEncoding == (unsigned long) kMelder_textOutputEncoding::UTF8) {
- if (kar <= 0x00'007F) {
- if (kar == U'\n' && file -> requiresCRLF)
- putc (13, f);
- putc ((int) kar, f); // guarded conversion down
- } else if (kar <= 0x00'07FF) {
- putc (0xC0 | (kar >> 6), f);
- putc (0x80 | (kar & 0x00'003F), f);
- } else if (kar <= 0x00'FFFF) {
- putc (0xE0 | (kar >> 12), f);
- putc (0x80 | ((kar >> 6) & 0x00'003F), f);
- putc (0x80 | (kar & 0x00'003F), f);
- } else {
- putc (0xF0 | (kar >> 18), f);
- putc (0x80 | ((kar >> 12) & 0x00'003F), f);
- putc (0x80 | ((kar >> 6) & 0x00'003F), f);
- putc (0x80 | (kar & 0x00'003F), f);
- }
- } else {
- if (kar == U'\n' && file -> requiresCRLF)
- binputu16 (13, f);
- if (kar <= 0x00'FFFF) {
- binputu16 ((uint16) kar, f);
- } else if (kar <= 0x10'FFFF) {
- kar -= 0x01'0000;
- binputu16 (0xD800 | (uint16) (kar >> 10), f);
- binputu16 (0xDC00 | (uint16) ((uint16) kar & 0x00'03ff), f);
- } else {
- binputu16 (UNICODE_REPLACEMENT_CHARACTER, f);
- }
- }
- }
- void MelderFile_seek (MelderFile me, integer position, int direction) {
- if (! my filePointer)
- return;
- if (fseek (my filePointer, position, direction)) {
- fclose (my filePointer);
- my filePointer = nullptr;
- Melder_throw (U"Cannot seek in file ", me, U".");
- }
- }
- integer MelderFile_tell (MelderFile me) {
- if (! my filePointer)
- return 0;
- integer result = ftell (my filePointer);
- if (result == -1) {
- fclose (my filePointer);
- my filePointer = nullptr;
- Melder_throw (U"Cannot tell in file ", me, U".");
- }
- return result;
- }
- void MelderFile_rewind (MelderFile me) {
- if (! my filePointer)
- return;
- rewind (my filePointer);
- }
- static void _MelderFile_close (MelderFile me, bool mayThrow) {
- if (my outputEncoding == kMelder_textOutputEncoding_FLAC) {
- if (my flacEncoder) {
- FLAC__stream_encoder_finish (my flacEncoder); // This already calls fclose! BUG: we cannot get any error messages out.
- FLAC__stream_encoder_delete (my flacEncoder);
- }
- } else if (my filePointer) {
- if (mayThrow) {
- Melder_fclose (me, my filePointer);
- } else {
- fclose (my filePointer);
- }
- }
- /* Set everything to zero, except paths (they stay around for error messages and the like). */
- my filePointer = nullptr;
- my openForWriting = my openForReading = false;
- my indent = 0;
- my flacEncoder = nullptr;
- }
- void MelderFile_close (MelderFile me) {
- _MelderFile_close (me, true);
- }
- void MelderFile_close_nothrow (MelderFile me) {
- _MelderFile_close (me, false);
- }
- /* End of file MelderFile.cpp */
|