TextFile: convert to a class
This commit is contained in:
parent
2452447c81
commit
90fe4c5124
@ -77,9 +77,8 @@ db_save_internal(FILE *fp, const Directory *music_root)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
db_load_internal(FILE *fp, Directory *music_root, GError **error)
|
db_load_internal(TextFile &file, Directory *music_root, GError **error)
|
||||||
{
|
{
|
||||||
GString *buffer = g_string_sized_new(1024);
|
|
||||||
char *line;
|
char *line;
|
||||||
int format = 0;
|
int format = 0;
|
||||||
bool found_charset = false, found_version = false;
|
bool found_charset = false, found_version = false;
|
||||||
@ -89,16 +88,15 @@ db_load_internal(FILE *fp, Directory *music_root, GError **error)
|
|||||||
assert(music_root != NULL);
|
assert(music_root != NULL);
|
||||||
|
|
||||||
/* get initial info */
|
/* get initial info */
|
||||||
line = read_text_line(fp, buffer);
|
line = file.ReadLine();
|
||||||
if (line == NULL || strcmp(DIRECTORY_INFO_BEGIN, line) != 0) {
|
if (line == NULL || strcmp(DIRECTORY_INFO_BEGIN, line) != 0) {
|
||||||
g_set_error(error, db_quark(), 0, "Database corrupted");
|
g_set_error(error, db_quark(), 0, "Database corrupted");
|
||||||
g_string_free(buffer, true);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(tags, false, sizeof(tags));
|
memset(tags, false, sizeof(tags));
|
||||||
|
|
||||||
while ((line = read_text_line(fp, buffer)) != NULL &&
|
while ((line = file.ReadLine()) != NULL &&
|
||||||
strcmp(line, DIRECTORY_INFO_END) != 0) {
|
strcmp(line, DIRECTORY_INFO_END) != 0) {
|
||||||
if (g_str_has_prefix(line, DB_FORMAT_PREFIX)) {
|
if (g_str_has_prefix(line, DB_FORMAT_PREFIX)) {
|
||||||
format = atoi(line + sizeof(DB_FORMAT_PREFIX) - 1);
|
format = atoi(line + sizeof(DB_FORMAT_PREFIX) - 1);
|
||||||
@ -106,7 +104,6 @@ db_load_internal(FILE *fp, Directory *music_root, GError **error)
|
|||||||
if (found_version) {
|
if (found_version) {
|
||||||
g_set_error(error, db_quark(), 0,
|
g_set_error(error, db_quark(), 0,
|
||||||
"Duplicate version line");
|
"Duplicate version line");
|
||||||
g_string_free(buffer, true);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +114,6 @@ db_load_internal(FILE *fp, Directory *music_root, GError **error)
|
|||||||
if (found_charset) {
|
if (found_charset) {
|
||||||
g_set_error(error, db_quark(), 0,
|
g_set_error(error, db_quark(), 0,
|
||||||
"Duplicate charset line");
|
"Duplicate charset line");
|
||||||
g_string_free(buffer, true);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +128,6 @@ db_load_internal(FILE *fp, Directory *music_root, GError **error)
|
|||||||
"\"%s\" instead of \"%s\"; "
|
"\"%s\" instead of \"%s\"; "
|
||||||
"discarding database file",
|
"discarding database file",
|
||||||
new_charset, old_charset);
|
new_charset, old_charset);
|
||||||
g_string_free(buffer, true);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (g_str_has_prefix(line, DB_TAG_PREFIX)) {
|
} else if (g_str_has_prefix(line, DB_TAG_PREFIX)) {
|
||||||
@ -150,7 +145,6 @@ db_load_internal(FILE *fp, Directory *music_root, GError **error)
|
|||||||
} else {
|
} else {
|
||||||
g_set_error(error, db_quark(), 0,
|
g_set_error(error, db_quark(), 0,
|
||||||
"Malformed line: %s", line);
|
"Malformed line: %s", line);
|
||||||
g_string_free(buffer, true);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,9 +168,8 @@ db_load_internal(FILE *fp, Directory *music_root, GError **error)
|
|||||||
g_debug("reading DB");
|
g_debug("reading DB");
|
||||||
|
|
||||||
db_lock();
|
db_lock();
|
||||||
success = directory_load(fp, music_root, buffer, error);
|
success = directory_load(file, music_root, error);
|
||||||
db_unlock();
|
db_unlock();
|
||||||
g_string_free(buffer, true);
|
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,12 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
struct Directory;
|
struct Directory;
|
||||||
|
class TextFile;
|
||||||
|
|
||||||
void
|
void
|
||||||
db_save_internal(FILE *file, const Directory *root);
|
db_save_internal(FILE *file, const Directory *root);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
db_load_internal(FILE *file, Directory *root, GError **error);
|
db_load_internal(TextFile &file, Directory *root, GError **error);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -76,10 +76,9 @@ directory_save(FILE *fp, const Directory *directory)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Directory *
|
static Directory *
|
||||||
directory_load_subdir(FILE *fp, Directory *parent, const char *name,
|
directory_load_subdir(TextFile &file, Directory *parent, const char *name,
|
||||||
GString *buffer, GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
const char *line;
|
|
||||||
bool success;
|
bool success;
|
||||||
|
|
||||||
if (parent->FindChild(name) != nullptr) {
|
if (parent->FindChild(name) != nullptr) {
|
||||||
@ -90,7 +89,7 @@ directory_load_subdir(FILE *fp, Directory *parent, const char *name,
|
|||||||
|
|
||||||
Directory *directory = parent->CreateChild(name);
|
Directory *directory = parent->CreateChild(name);
|
||||||
|
|
||||||
line = read_text_line(fp, buffer);
|
const char *line = file.ReadLine();
|
||||||
if (line == NULL) {
|
if (line == NULL) {
|
||||||
g_set_error(error_r, directory_quark(), 0,
|
g_set_error(error_r, directory_quark(), 0,
|
||||||
"Unexpected end of file");
|
"Unexpected end of file");
|
||||||
@ -103,7 +102,7 @@ directory_load_subdir(FILE *fp, Directory *parent, const char *name,
|
|||||||
g_ascii_strtoull(line + sizeof(DIRECTORY_MTIME) - 1,
|
g_ascii_strtoull(line + sizeof(DIRECTORY_MTIME) - 1,
|
||||||
NULL, 10);
|
NULL, 10);
|
||||||
|
|
||||||
line = read_text_line(fp, buffer);
|
line = file.ReadLine();
|
||||||
if (line == NULL) {
|
if (line == NULL) {
|
||||||
g_set_error(error_r, directory_quark(), 0,
|
g_set_error(error_r, directory_quark(), 0,
|
||||||
"Unexpected end of file");
|
"Unexpected end of file");
|
||||||
@ -119,7 +118,7 @@ directory_load_subdir(FILE *fp, Directory *parent, const char *name,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
success = directory_load(fp, directory, buffer, error_r);
|
success = directory_load(file, directory, error_r);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
directory->Delete();
|
directory->Delete();
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -129,18 +128,17 @@ directory_load_subdir(FILE *fp, Directory *parent, const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
directory_load(FILE *fp, Directory *directory,
|
directory_load(TextFile &file, Directory *directory, GError **error)
|
||||||
GString *buffer, GError **error)
|
|
||||||
{
|
{
|
||||||
const char *line;
|
const char *line;
|
||||||
|
|
||||||
while ((line = read_text_line(fp, buffer)) != NULL &&
|
while ((line = file.ReadLine()) != NULL &&
|
||||||
!g_str_has_prefix(line, DIRECTORY_END)) {
|
!g_str_has_prefix(line, DIRECTORY_END)) {
|
||||||
if (g_str_has_prefix(line, DIRECTORY_DIR)) {
|
if (g_str_has_prefix(line, DIRECTORY_DIR)) {
|
||||||
Directory *subdir =
|
Directory *subdir =
|
||||||
directory_load_subdir(fp, directory,
|
directory_load_subdir(file, directory,
|
||||||
line + sizeof(DIRECTORY_DIR) - 1,
|
line + sizeof(DIRECTORY_DIR) - 1,
|
||||||
buffer, error);
|
error);
|
||||||
if (subdir == NULL)
|
if (subdir == NULL)
|
||||||
return false;
|
return false;
|
||||||
} else if (g_str_has_prefix(line, SONG_BEGIN)) {
|
} else if (g_str_has_prefix(line, SONG_BEGIN)) {
|
||||||
@ -153,8 +151,7 @@ directory_load(FILE *fp, Directory *directory,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
song = song_load(fp, directory, name,
|
song = song_load(file, directory, name, error);
|
||||||
buffer, error);
|
|
||||||
if (song == NULL)
|
if (song == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -165,8 +162,8 @@ directory_load(FILE *fp, Directory *directory,
|
|||||||
buffer */
|
buffer */
|
||||||
char *name = g_strdup(line + sizeof(PLAYLIST_META_BEGIN) - 1);
|
char *name = g_strdup(line + sizeof(PLAYLIST_META_BEGIN) - 1);
|
||||||
|
|
||||||
if (!playlist_metadata_load(fp, directory->playlists,
|
if (!playlist_metadata_load(file, directory->playlists,
|
||||||
name, buffer, error)) {
|
name, error)) {
|
||||||
g_free(name);
|
g_free(name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,12 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
struct Directory;
|
struct Directory;
|
||||||
|
class TextFile;
|
||||||
|
|
||||||
void
|
void
|
||||||
directory_save(FILE *fp, const Directory *directory);
|
directory_save(FILE *fp, const Directory *directory);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
directory_load(FILE *fp, Directory *directory,
|
directory_load(TextFile &file, Directory *directory, GError **error);
|
||||||
GString *buffer, GError **error);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -46,15 +46,15 @@ playlist_vector_save(FILE *fp, const PlaylistVector &pv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
playlist_metadata_load(FILE *fp, PlaylistVector &pv, const char *name,
|
playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name,
|
||||||
GString *buffer, GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
PlaylistInfo pm(name, 0);
|
PlaylistInfo pm(name, 0);
|
||||||
|
|
||||||
char *line, *colon;
|
char *line, *colon;
|
||||||
const char *value;
|
const char *value;
|
||||||
|
|
||||||
while ((line = read_text_line(fp, buffer)) != NULL &&
|
while ((line = file.ReadLine()) != NULL &&
|
||||||
strcmp(line, "playlist_end") != 0) {
|
strcmp(line, "playlist_end") != 0) {
|
||||||
colon = strchr(line, ':');
|
colon = strchr(line, ':');
|
||||||
if (colon == NULL || colon == line) {
|
if (colon == NULL || colon == line) {
|
||||||
|
@ -28,12 +28,13 @@
|
|||||||
#define PLAYLIST_META_BEGIN "playlist_begin: "
|
#define PLAYLIST_META_BEGIN "playlist_begin: "
|
||||||
|
|
||||||
class PlaylistVector;
|
class PlaylistVector;
|
||||||
|
class TextFile;
|
||||||
|
|
||||||
void
|
void
|
||||||
playlist_vector_save(FILE *fp, const PlaylistVector &pv);
|
playlist_vector_save(FILE *fp, const PlaylistVector &pv);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
playlist_metadata_load(FILE *fp, PlaylistVector &pv, const char *name,
|
playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name,
|
||||||
GString *buffer, GError **error_r);
|
GError **error_r);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -236,16 +236,14 @@ LoadPlaylistFile(const char *utf8path, GError **error_r)
|
|||||||
if (path_fs == NULL)
|
if (path_fs == NULL)
|
||||||
return contents;
|
return contents;
|
||||||
|
|
||||||
FILE *file = fopen(path_fs, "r");
|
TextFile file(path_fs);
|
||||||
g_free(path_fs);
|
if (file.HasFailed()) {
|
||||||
if (file == NULL) {
|
|
||||||
playlist_errno(error_r);
|
playlist_errno(error_r);
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
GString *buffer = g_string_sized_new(1024);
|
|
||||||
char *s;
|
char *s;
|
||||||
while ((s = read_text_line(file, buffer)) != NULL) {
|
while ((s = file.ReadLine()) != NULL) {
|
||||||
if (*s == 0 || *s == PLAYLIST_COMMENT)
|
if (*s == 0 || *s == PLAYLIST_COMMENT)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -265,7 +263,6 @@ LoadPlaylistFile(const char *utf8path, GError **error_r)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,18 +104,18 @@ playlist_state_save(FILE *fp, const struct playlist *playlist,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
playlist_state_load(FILE *fp, GString *buffer, struct playlist *playlist)
|
playlist_state_load(TextFile &file, struct playlist *playlist)
|
||||||
{
|
{
|
||||||
const char *line = read_text_line(fp, buffer);
|
const char *line = file.ReadLine();
|
||||||
if (line == NULL) {
|
if (line == NULL) {
|
||||||
g_warning("No playlist in state file");
|
g_warning("No playlist in state file");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!g_str_has_prefix(line, PLAYLIST_STATE_FILE_PLAYLIST_END)) {
|
while (!g_str_has_prefix(line, PLAYLIST_STATE_FILE_PLAYLIST_END)) {
|
||||||
queue_load_song(fp, buffer, line, &playlist->queue);
|
queue_load_song(file, line, &playlist->queue);
|
||||||
|
|
||||||
line = read_text_line(fp, buffer);
|
line = file.ReadLine();
|
||||||
if (line == NULL) {
|
if (line == NULL) {
|
||||||
g_warning("'" PLAYLIST_STATE_FILE_PLAYLIST_END
|
g_warning("'" PLAYLIST_STATE_FILE_PLAYLIST_END
|
||||||
"' not found in state file");
|
"' not found in state file");
|
||||||
@ -127,7 +127,7 @@ playlist_state_load(FILE *fp, GString *buffer, struct playlist *playlist)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
playlist_state_restore(const char *line, FILE *fp, GString *buffer,
|
playlist_state_restore(const char *line, TextFile &file,
|
||||||
struct playlist *playlist, struct player_control *pc)
|
struct playlist *playlist, struct player_control *pc)
|
||||||
{
|
{
|
||||||
int current = -1;
|
int current = -1;
|
||||||
@ -145,7 +145,7 @@ playlist_state_restore(const char *line, FILE *fp, GString *buffer,
|
|||||||
else if (strcmp(line, PLAYLIST_STATE_FILE_STATE_PAUSE) == 0)
|
else if (strcmp(line, PLAYLIST_STATE_FILE_STATE_PAUSE) == 0)
|
||||||
state = PLAYER_STATE_PAUSE;
|
state = PLAYER_STATE_PAUSE;
|
||||||
|
|
||||||
while ((line = read_text_line(fp, buffer)) != NULL) {
|
while ((line = file.ReadLine()) != NULL) {
|
||||||
if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_TIME)) {
|
if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_TIME)) {
|
||||||
seek_time =
|
seek_time =
|
||||||
atoi(&(line[strlen(PLAYLIST_STATE_FILE_TIME)]));
|
atoi(&(line[strlen(PLAYLIST_STATE_FILE_TIME)]));
|
||||||
@ -189,7 +189,7 @@ playlist_state_restore(const char *line, FILE *fp, GString *buffer,
|
|||||||
(PLAYLIST_STATE_FILE_CURRENT)]));
|
(PLAYLIST_STATE_FILE_CURRENT)]));
|
||||||
} else if (g_str_has_prefix(line,
|
} else if (g_str_has_prefix(line,
|
||||||
PLAYLIST_STATE_FILE_PLAYLIST_BEGIN)) {
|
PLAYLIST_STATE_FILE_PLAYLIST_BEGIN)) {
|
||||||
playlist_state_load(fp, buffer, playlist);
|
playlist_state_load(file, playlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,13 +30,14 @@
|
|||||||
|
|
||||||
struct playlist;
|
struct playlist;
|
||||||
struct player_control;
|
struct player_control;
|
||||||
|
class TextFile;
|
||||||
|
|
||||||
void
|
void
|
||||||
playlist_state_save(FILE *fp, const struct playlist *playlist,
|
playlist_state_save(FILE *fp, const struct playlist *playlist,
|
||||||
struct player_control *pc);
|
struct player_control *pc);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
playlist_state_restore(const char *line, FILE *fp, GString *buffer,
|
playlist_state_restore(const char *line, TextFile &file,
|
||||||
struct playlist *playlist, struct player_control *pc);
|
struct playlist *playlist, struct player_control *pc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,8 +71,7 @@ queue_save(FILE *fp, const struct queue *queue)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
queue_load_song(FILE *fp, GString *buffer, const char *line,
|
queue_load_song(TextFile &file, const char *line, queue *queue)
|
||||||
struct queue *queue)
|
|
||||||
{
|
{
|
||||||
if (queue_is_full(queue))
|
if (queue_is_full(queue))
|
||||||
return;
|
return;
|
||||||
@ -81,7 +80,7 @@ queue_load_song(FILE *fp, GString *buffer, const char *line,
|
|||||||
if (g_str_has_prefix(line, PRIO_LABEL)) {
|
if (g_str_has_prefix(line, PRIO_LABEL)) {
|
||||||
priority = strtoul(line + sizeof(PRIO_LABEL) - 1, NULL, 10);
|
priority = strtoul(line + sizeof(PRIO_LABEL) - 1, NULL, 10);
|
||||||
|
|
||||||
line = read_text_line(fp, buffer);
|
line = file.ReadLine();
|
||||||
if (line == NULL)
|
if (line == NULL)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -95,7 +94,7 @@ queue_load_song(FILE *fp, GString *buffer, const char *line,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
song = song_load(fp, NULL, uri, buffer, &error);
|
song = song_load(file, NULL, uri, &error);
|
||||||
if (song == NULL) {
|
if (song == NULL) {
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
struct queue;
|
struct queue;
|
||||||
|
class TextFile;
|
||||||
|
|
||||||
void
|
void
|
||||||
queue_save(FILE *fp, const struct queue *queue);
|
queue_save(FILE *fp, const struct queue *queue);
|
||||||
@ -37,7 +38,6 @@ queue_save(FILE *fp, const struct queue *queue);
|
|||||||
* Loads one song from the state file and appends it to the queue.
|
* Loads one song from the state file and appends it to the queue.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
queue_load_song(FILE *fp, GString *buffer, const char *line,
|
queue_load_song(TextFile &file, const char *line, queue *queue);
|
||||||
struct queue *queue);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -63,8 +63,8 @@ song_save(FILE *fp, const struct song *song)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct song *
|
struct song *
|
||||||
song_load(FILE *fp, Directory *parent, const char *uri,
|
song_load(TextFile &file, Directory *parent, const char *uri,
|
||||||
GString *buffer, GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
struct song *song = parent != NULL
|
struct song *song = parent != NULL
|
||||||
? song_file_new(uri, parent)
|
? song_file_new(uri, parent)
|
||||||
@ -73,7 +73,7 @@ song_load(FILE *fp, Directory *parent, const char *uri,
|
|||||||
enum tag_type type;
|
enum tag_type type;
|
||||||
const char *value;
|
const char *value;
|
||||||
|
|
||||||
while ((line = read_text_line(fp, buffer)) != NULL &&
|
while ((line = file.ReadLine()) != NULL &&
|
||||||
strcmp(line, SONG_END) != 0) {
|
strcmp(line, SONG_END) != 0) {
|
||||||
colon = strchr(line, ':');
|
colon = strchr(line, ':');
|
||||||
if (colon == NULL || colon == line) {
|
if (colon == NULL || colon == line) {
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
struct song;
|
struct song;
|
||||||
struct Directory;
|
struct Directory;
|
||||||
|
class TextFile;
|
||||||
|
|
||||||
void
|
void
|
||||||
song_save(FILE *fp, const struct song *song);
|
song_save(FILE *fp, const struct song *song);
|
||||||
@ -41,7 +42,7 @@ song_save(FILE *fp, const struct song *song);
|
|||||||
* @return true on success, false on error
|
* @return true on success, false on error
|
||||||
*/
|
*/
|
||||||
struct song *
|
struct song *
|
||||||
song_load(FILE *fp, Directory *parent, const char *uri,
|
song_load(TextFile &file, Directory *parent, const char *uri,
|
||||||
GString *buffer, GError **error_r);
|
GError **error_r);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -78,39 +78,31 @@ state_file_write(struct player_control *pc)
|
|||||||
static void
|
static void
|
||||||
state_file_read(struct player_control *pc)
|
state_file_read(struct player_control *pc)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
|
||||||
bool success;
|
bool success;
|
||||||
|
|
||||||
assert(state_file_path != NULL);
|
assert(state_file_path != NULL);
|
||||||
|
|
||||||
g_debug("Loading state file %s", state_file_path);
|
g_debug("Loading state file %s", state_file_path);
|
||||||
|
|
||||||
fp = fopen(state_file_path, "r");
|
TextFile file(state_file_path);
|
||||||
if (G_UNLIKELY(!fp)) {
|
if (file.HasFailed()) {
|
||||||
g_warning("failed to open %s: %s",
|
g_warning("failed to open %s: %s",
|
||||||
state_file_path, g_strerror(errno));
|
state_file_path, g_strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GString *buffer = g_string_sized_new(1024);
|
|
||||||
const char *line;
|
const char *line;
|
||||||
while ((line = read_text_line(fp, buffer)) != NULL) {
|
while ((line = file.ReadLine()) != NULL) {
|
||||||
success = read_sw_volume_state(line) ||
|
success = read_sw_volume_state(line) ||
|
||||||
audio_output_state_read(line) ||
|
audio_output_state_read(line) ||
|
||||||
playlist_state_restore(line, fp, buffer,
|
playlist_state_restore(line, file, &g_playlist, pc);
|
||||||
&g_playlist, pc);
|
|
||||||
if (!success)
|
if (!success)
|
||||||
g_warning("Unrecognized line in state file: %s", line);
|
g_warning("Unrecognized line in state file: %s", line);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
prev_volume_version = sw_volume_state_get_hash();
|
prev_volume_version = sw_volume_state_get_hash();
|
||||||
prev_output_version = audio_output_state_get_version();
|
prev_output_version = audio_output_state_get_version();
|
||||||
prev_playlist_version = playlist_state_get_hash(&g_playlist, pc);
|
prev_playlist_version = playlist_state_get_hash(&g_playlist, pc);
|
||||||
|
|
||||||
|
|
||||||
g_string_free(buffer, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,21 +24,14 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
char *
|
char *
|
||||||
read_text_line(FILE *file, GString *buffer)
|
TextFile::ReadLine()
|
||||||
{
|
{
|
||||||
enum {
|
|
||||||
max_length = 512 * 1024,
|
|
||||||
step = 1024,
|
|
||||||
};
|
|
||||||
|
|
||||||
gsize length = 0, i;
|
gsize length = 0, i;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
assert(file != NULL);
|
assert(file != NULL);
|
||||||
assert(buffer != NULL);
|
assert(buffer != NULL);
|
||||||
|
assert(buffer->allocated_len >= step);
|
||||||
if (buffer->allocated_len < step)
|
|
||||||
g_string_set_size(buffer, step);
|
|
||||||
|
|
||||||
while (buffer->len < max_length) {
|
while (buffer->len < max_length) {
|
||||||
p = fgets(buffer->str + length,
|
p = fgets(buffer->str + length,
|
||||||
|
@ -20,20 +20,47 @@
|
|||||||
#ifndef MPD_TEXT_FILE_HXX
|
#ifndef MPD_TEXT_FILE_HXX
|
||||||
#define MPD_TEXT_FILE_HXX
|
#define MPD_TEXT_FILE_HXX
|
||||||
|
|
||||||
|
#include "gcc.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/**
|
class TextFile {
|
||||||
* Reads a line from the input file, and strips trailing space. There
|
static constexpr size_t max_length = 512 * 1024;
|
||||||
* is a reasonable maximum line length, only to prevent denial of
|
static constexpr size_t step = 1024;
|
||||||
* service.
|
|
||||||
*
|
FILE *const file;
|
||||||
* @param file the source file, opened in text mode
|
|
||||||
* @param buffer an allocator for the buffer
|
GString *const buffer;
|
||||||
* @return a pointer to the line, or NULL on end-of-file or error
|
|
||||||
*/
|
public:
|
||||||
char *
|
TextFile(const char *path_fs)
|
||||||
read_text_line(FILE *file, GString *buffer);
|
:file(fopen(path_fs, "r")), buffer(g_string_sized_new(step)) {}
|
||||||
|
|
||||||
|
TextFile(const TextFile &other) = delete;
|
||||||
|
|
||||||
|
~TextFile() {
|
||||||
|
if (file != nullptr)
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
g_string_free(buffer, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasFailed() const {
|
||||||
|
return gcc_unlikely(file == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a line from the input file, and strips trailing
|
||||||
|
* space. There is a reasonable maximum line length, only to
|
||||||
|
* prevent denial of service.
|
||||||
|
*
|
||||||
|
* @param file the source file, opened in text mode
|
||||||
|
* @param buffer an allocator for the buffer
|
||||||
|
* @return a pointer to the line, or NULL on end-of-file or error
|
||||||
|
*/
|
||||||
|
char *ReadLine();
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "DatabaseSave.hxx"
|
#include "DatabaseSave.hxx"
|
||||||
#include "DatabaseLock.hxx"
|
#include "DatabaseLock.hxx"
|
||||||
#include "db_error.h"
|
#include "db_error.h"
|
||||||
|
#include "TextFile.hxx"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
@ -155,20 +156,16 @@ SimpleDatabase::Load(GError **error_r)
|
|||||||
assert(!path.empty());
|
assert(!path.empty());
|
||||||
assert(root != NULL);
|
assert(root != NULL);
|
||||||
|
|
||||||
FILE *fp = fopen(path.c_str(), "r");
|
TextFile file(path.c_str());
|
||||||
if (fp == NULL) {
|
if (file.HasFailed()) {
|
||||||
g_set_error(error_r, simple_db_quark(), errno,
|
g_set_error(error_r, simple_db_quark(), errno,
|
||||||
"Failed to open database file \"%s\": %s",
|
"Failed to open database file \"%s\": %s",
|
||||||
path.c_str(), g_strerror(errno));
|
path.c_str(), g_strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!db_load_internal(fp, root, error_r)) {
|
if (!db_load_internal(file, root, error_r))
|
||||||
fclose(fp);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(path.c_str(), &st) == 0)
|
if (stat(path.c_str(), &st) == 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user