blob: 6e87cda14a81e4fc917155e9b6b1f701de729fb7 [file] [edit]
/*############################################################################
# Copyright 2016-2017 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
############################################################################*/
/*!
* \file
* \brief Buffer handling utilities implementation.
*/
#include <util/buffutil.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include "util/envutil.h"
/// file static variable that indicates verbose logging
static bool g_bufutil_verbose = false;
bool ToggleVerbosity() {
g_bufutil_verbose = (g_bufutil_verbose) ? false : true;
return g_bufutil_verbose;
}
bool FileExists(char const* filename) {
FILE* fp = NULL;
if (!filename || !filename[0]) {
return false;
}
fp = fopen(filename, "rb");
if (fp) {
fclose(fp);
return true;
}
return false;
}
size_t GetFileSize(char const* filename) {
size_t file_length = 0;
FILE* fp = fopen(filename, "rb");
if (fp) {
fseek(fp, 0, SEEK_END);
file_length = ftell(fp);
fclose(fp);
}
return file_length;
}
size_t GetFileSize_S(char const* filename, size_t max_size) {
size_t size = GetFileSize(filename);
if (size > max_size) {
return 0;
} else {
return size;
}
}
void* AllocBuffer(size_t size) {
void* buffer = NULL;
if (size) {
buffer = malloc(size);
}
if (!buffer) {
log_error("failed to allocate memory");
}
return buffer;
}
void* NewBufferFromFile(const char* filename, size_t* size) {
void* buffer = NULL;
do {
size_t len = 0;
if (!FileExists(filename)) {
log_error("cannot access '%s'", filename);
break;
}
len = GetFileSize_S(filename, SIZE_MAX);
if (len == 0) {
log_error("cannot load empty file '%s'", filename);
break;
}
buffer = AllocBuffer(len);
if (buffer) {
if (0 != ReadLoud(filename, buffer, len)) {
free(buffer);
buffer = NULL;
break;
}
}
if (size) {
*size = len;
}
} while (0);
return buffer;
}
int ReadBufferFromFile(const char* filename, void* buffer, size_t size) {
int result = 0;
FILE* file = NULL;
do {
size_t bytes_read = 0;
size_t file_size = 0;
file = fopen(filename, "rb");
if (!file) {
result = -1;
break;
}
fseek(file, 0, SEEK_END);
file_size = ftell(file);
fseek(file, 0, SEEK_SET);
if ((size_t)file_size != size) {
result = -1;
break;
}
if (buffer && (0 != size)) {
bytes_read = fread(buffer, 1, size, file);
if (bytes_read != size) {
result = -1;
break;
}
}
} while (0);
if (file) {
fclose(file);
}
return result;
}
int WriteBufferToFile(const void* buffer, size_t size, const char* filename) {
int result = 0;
FILE* file = NULL;
do {
size_t bytes_written = 0;
file = fopen(filename, "wb");
if (!file) {
result = -1;
break;
}
bytes_written = fwrite(buffer, 1, size, file);
if (bytes_written != size) {
result = -1;
break;
}
} while (0);
if (file) {
fclose(file);
}
return result;
}
int ReadLoud(char const* filename, void* buf, size_t size) {
int result;
if (!buf || 0 == size) {
log_error("internal error: invalid buffer to ReadLoud");
return -1;
}
if (g_bufutil_verbose) {
log_msg("reading %s", filename);
}
if (!FileExists(filename)) {
log_error("cannot access '%s' for reading", filename);
return -1;
}
if (size != GetFileSize(filename)) {
log_error("unexpected file size for '%s'. Expected: %d; got: %d", filename,
(int)size, (int)GetFileSize(filename));
return -1;
}
result = ReadBufferFromFile(filename, buf, size);
if (0 != result) {
log_error("failed to read from `%s`", filename);
return result;
}
if (g_bufutil_verbose) {
PrintBuffer(buf, size);
}
return result;
}
int WriteLoud(void* buf, size_t size, char const* filename) {
int result = -1;
if (!buf || 0 == size) {
log_error("internal error: invalid buffer to WriteLoud");
return -1;
}
if (g_bufutil_verbose) {
log_msg("writing %s", filename);
}
result = WriteBufferToFile(buf, size, filename);
if (0 != result) {
log_error("failed to write to `%s`", filename);
return result;
}
if (g_bufutil_verbose) {
PrintBuffer(buf, size);
}
return result;
}
void PrintBuffer(const void* buffer, size_t size) {
BufferPrintOptions opts;
opts.show_header = true;
opts.show_offset = true;
opts.show_hex = true;
opts.show_ascii = true;
opts.bytes_per_group = 2;
opts.groups_per_line = 8;
PrintBufferOpt(buffer, size, opts);
}
void PrintBufferOpt(const void* buffer, size_t size, BufferPrintOptions opts) {
unsigned char* bytes = (unsigned char*)buffer;
size_t bytes_per_line = opts.bytes_per_group * opts.groups_per_line;
size_t line_offset = 0;
size_t byte_offset = 0;
size_t byte_col = 0;
if (opts.show_header) {
if (opts.show_offset) {
log_fmt(" offset");
log_fmt(": ");
}
if (opts.show_hex) {
byte_col = 0;
while (byte_col < bytes_per_line) {
log_fmt("%x%x", (int)byte_col, (int)byte_col);
if (0 == (byte_col + 1) % opts.bytes_per_group) {
log_fmt(" ");
}
byte_col += 1;
}
}
if (opts.show_hex && opts.show_ascii) {
log_fmt("| ");
}
if (opts.show_ascii) {
byte_col = 0;
while (byte_col < bytes_per_line) {
log_fmt("%x", (int)byte_col);
byte_col += 1;
}
}
log_fmt("\n");
if (opts.show_offset) {
log_fmt("--------");
log_fmt(": ");
}
if (opts.show_hex) {
byte_col = 0;
while (byte_col < bytes_per_line) {
log_fmt("--");
if (0 == (byte_col + 1) % opts.bytes_per_group) {
log_fmt("-");
}
byte_col += 1;
}
}
if (opts.show_hex && opts.show_ascii) {
log_fmt("|-");
}
if (opts.show_ascii) {
byte_col = 0;
while (byte_col < bytes_per_line) {
log_fmt("-");
byte_col += 1;
}
}
log_fmt("\n");
}
line_offset = 0;
while (line_offset < size) {
if (opts.show_offset) {
log_fmt("%08x", (int)line_offset);
log_fmt(": ");
}
if (opts.show_hex) {
byte_col = 0;
while (byte_col < bytes_per_line) {
byte_offset = line_offset + byte_col;
if (byte_offset < size) {
log_fmt("%02x", (int)bytes[byte_offset]);
} else {
log_fmt(" ");
}
if (0 == (byte_col + 1) % opts.bytes_per_group) {
log_fmt(" ");
}
byte_col += 1;
}
}
if (opts.show_hex && opts.show_ascii) {
log_fmt("| ");
}
if (opts.show_ascii) {
byte_col = 0;
while (byte_col < bytes_per_line) {
byte_offset = line_offset + byte_col;
if (byte_offset < size) {
unsigned char ch = bytes[byte_offset];
if (isprint(ch)) {
log_fmt("%c", ch);
} else {
log_fmt(".");
}
} else {
log_fmt(" ");
}
byte_col += 1;
}
}
log_fmt("\n");
line_offset += bytes_per_line;
}
}