Browse Source

Clean up `package log` code

gingerBill 5 years ago
parent
commit
9f596d6f34
4 changed files with 150 additions and 152 deletions
  1. 3 1
      core/fmt/fmt.odin
  2. 95 97
      core/log/file_console_logger.odin
  3. 47 49
      core/log/log.odin
  4. 5 5
      core/runtime/core.odin

+ 3 - 1
core/fmt/fmt.odin

@@ -1007,7 +1007,9 @@ fmt_enum :: proc(fi: ^Info, v: any, verb: rune) {
 			fmt_arg(fi, any{v.data, runtime.type_info_base(e.base).id}, verb);
 		case 's', 'v':
 			str, ok := enum_value_to_string(v);
-			if !ok do str = "!%(BAD ENUM VALUE)";
+			if !ok {
+				str = "!%(BAD ENUM VALUE)";
+			}
 			strings.write_string(fi.buf, str);
 		}
 	}

+ 95 - 97
core/log/file_console_logger.odin

@@ -5,133 +5,131 @@ import "core:strings";
 import "core:os";
 import "core:time";
 
-Level_Headers := []string{
-    "[DEBUG] --- ",
-    "[INFO ] --- ",
-    "[WARN ] --- ",
-    "[ERROR] --- ",
-    "[FATAL] --- ",
+Level_Headers := [?]string{
+	 0..<10 = "[DEBUG] --- ",
+	10..<20 = "[INFO ] --- ",
+	20..<30 = "[WARN ] --- ",
+	30..<40 = "[ERROR] --- ",
+	40..<50 = "[FATAL] --- ",
 };
 
 Default_Console_Logger_Opts :: Options{
-    .Level,
-    .Terminal_Color,
-    .Short_File_Path,
-    .Line,
-    .Procedure,
+	.Level,
+	.Terminal_Color,
+	.Short_File_Path,
+	.Line,
+	.Procedure,
 } | Full_Timestamp_Opts;
 
 Default_File_Logger_Opts :: Options{
-    .Level,
-    .Short_File_Path,
-    .Line,
-    .Procedure,
+	.Level,
+	.Short_File_Path,
+	.Line,
+	.Procedure,
 } | Full_Timestamp_Opts;
 
 
 File_Console_Logger_Data :: struct {
-    file_handle:  os.Handle,
-    ident : string,
+	file_handle:  os.Handle,
+	ident: string,
 }
 
 create_file_logger :: proc(h: os.Handle, lowest := Level.Debug, opt := Default_File_Logger_Opts, ident := "") -> Logger {
-    data := new(File_Console_Logger_Data);
-    data.file_handle = h;
-    data.ident = ident;
-    return Logger{file_console_logger_proc, data, lowest, opt};
+	data := new(File_Console_Logger_Data);
+	data.file_handle = h;
+	data.ident = ident;
+	return Logger{file_console_logger_proc, data, lowest, opt};
 }
 
-destroy_file_logger ::proc(log : ^Logger) {
-    data := cast(^File_Console_Logger_Data)log.data;
-    if data.file_handle != os.INVALID_HANDLE do os.close(data.file_handle);
-    free(data);
-    log^ = nil_logger();
+destroy_file_logger :: proc(log: ^Logger) {
+	data := cast(^File_Console_Logger_Data)log.data;
+	if data.file_handle != os.INVALID_HANDLE do os.close(data.file_handle);
+	free(data);
 }
 
 create_console_logger :: proc(lowest := Level.Debug, opt := Default_Console_Logger_Opts, ident := "") -> Logger {
-    data := new(File_Console_Logger_Data);
-    data.file_handle = os.INVALID_HANDLE;
-    data.ident = ident;
-    return Logger{file_console_logger_proc, data, lowest, opt};
+	data := new(File_Console_Logger_Data);
+	data.file_handle = os.INVALID_HANDLE;
+	data.ident = ident;
+	return Logger{file_console_logger_proc, data, lowest, opt};
 }
 
-destroy_console_logger ::proc(log : ^Logger) {
-    free(log.data);
-    log^ = nil_logger();
+destroy_console_logger :: proc(log: ^Logger) {
+	free(log.data);
 }
 
 file_console_logger_proc :: proc(logger_data: rawptr, level: Level, text: string, options: Options, location := #caller_location) {
-    data := cast(^File_Console_Logger_Data)logger_data;
-    h : os.Handle;
-    if(data.file_handle != os.INVALID_HANDLE) do h = data.file_handle;
-    else                                      do h = os.stdout if level <= Level.Error else os.stderr;
-    backing: [1024]byte; //NOTE(Hoej): 1024 might be too much for a header backing, unless somebody has really long paths.
-    buf := strings.builder_from_slice(backing[:]);
-
-    do_level_header(options, level, &buf);
-
-    when time.IS_SUPPORTED {
-        if Full_Timestamp_Opts & options != nil {
-            fmt.sbprint(&buf, "[");
-            t := time.now();
-            y, m, d := time.date(t);
-            h, min, s := time.clock(t);
-            if Option.Date in options do fmt.sbprintf(&buf, "%d-%02d-%02d ", y, m, d);
-            if Option.Time in options do fmt.sbprintf(&buf, "%02d:%02d:%02d", h, min, s);
-            fmt.sbprint(&buf, "] ");
-        }
-    }
-
-    do_location_header(options, &buf, location);
-
-    if data.ident != "" do fmt.sbprintf(&buf, "[%s] ", data.ident);
-    //TODO(Hoej): When we have better atomics and such, make this thread-safe
-    fmt.fprintf(h, "%s %s\n", strings.to_string(buf), text);
+	data := cast(^File_Console_Logger_Data)logger_data;
+	h: os.Handle;
+	if(data.file_handle != os.INVALID_HANDLE) do h = data.file_handle;
+	else                                      do h = os.stdout if level <= Level.Error else os.stderr;
+	backing: [1024]byte; //NOTE(Hoej): 1024 might be too much for a header backing, unless somebody has really long paths.
+	buf := strings.builder_from_slice(backing[:]);
+
+	do_level_header(options, level, &buf);
+
+	when time.IS_SUPPORTED {
+		if Full_Timestamp_Opts & options != nil {
+			fmt.sbprint(&buf, "[");
+			t := time.now();
+			y, m, d := time.date(t);
+			h, min, s := time.clock(t);
+			if Option.Date in options do fmt.sbprintf(&buf, "%d-%02d-%02d ", y, m, d);
+			if Option.Time in options do fmt.sbprintf(&buf, "%02d:%02d:%02d", h, min, s);
+			fmt.sbprint(&buf, "] ");
+		}
+	}
+
+	do_location_header(options, &buf, location);
+
+	if data.ident != "" do fmt.sbprintf(&buf, "[%s] ", data.ident);
+	//TODO(Hoej): When we have better atomics and such, make this thread-safe
+	fmt.fprintf(h, "%s %s\n", strings.to_string(buf), text);
 }
 
-do_level_header :: proc(opts : Options, level : Level, str : ^strings.Builder) {
-
-    RESET     :: "\x1b[0m";
-    RED       :: "\x1b[31m";
-    YELLOW    :: "\x1b[33m";
-    DARK_GREY :: "\x1b[90m";
-
-    col := RESET;
-    switch level {
-    case Level.Debug              : col = DARK_GREY;
-    case Level.Info               : col = RESET;
-    case Level.Warning            : col = YELLOW;
-    case Level.Error, Level.Fatal : col = RED;
-    }
-
-    if .Level in opts {
-        if .Terminal_Color in opts do fmt.sbprint(str, col);
-        fmt.sbprint(str, Level_Headers[level]);
-        if .Terminal_Color in opts do fmt.sbprint(str, RESET);
-    }
+do_level_header :: proc(opts: Options, level: Level, str: ^strings.Builder) {
+
+	RESET     :: "\x1b[0m";
+	RED       :: "\x1b[31m";
+	YELLOW    :: "\x1b[33m";
+	DARK_GREY :: "\x1b[90m";
+
+	col := RESET;
+	switch level {
+	case .Debug:   col = DARK_GREY;
+	case .Info:    col = RESET;
+	case .Warning: col = YELLOW;
+	case .Error, .Fatal: col = RED;
+	}
+
+	if .Level in opts {
+		if .Terminal_Color in opts do fmt.sbprint(str, col);
+		fmt.sbprint(str, Level_Headers[level]);
+		if .Terminal_Color in opts do fmt.sbprint(str, RESET);
+	}
 }
 
-do_location_header :: proc(opts : Options, buf : ^strings.Builder, location := #caller_location) {
-    if Location_Header_Opts & opts != nil do fmt.sbprint(buf, "["); else do return;
+do_location_header :: proc(opts: Options, buf: ^strings.Builder, location := #caller_location) {
+	if Location_Header_Opts & opts != nil do fmt.sbprint(buf, "["); else do return;
 
-    file := location.file_path;
-    if .Short_File_Path in opts {
-        last := 0;
-        for r, i in location.file_path do if r == '/' do last = i+1;
-        file = location.file_path[last:];
-    }
+	file := location.file_path;
+	if .Short_File_Path in opts {
+		last := 0;
+		for r, i in location.file_path do if r == '/' do last = i+1;
+		file = location.file_path[last:];
+	}
 
-    if Location_File_Opts & opts != nil do fmt.sbprint(buf, file);
+	if Location_File_Opts & opts != nil do fmt.sbprint(buf, file);
 
-    if .Procedure in opts {
-        if Location_File_Opts & opts != nil do fmt.sbprint(buf, ".");
-        fmt.sbprintf(buf, "%s()", location.procedure);
-    }
+	if .Procedure in opts {
+		if Location_File_Opts & opts != nil do fmt.sbprint(buf, ".");
+		fmt.sbprintf(buf, "%s()", location.procedure);
+	}
 
-    if .Line in opts {
-        if Location_File_Opts & opts != nil || .Procedure in opts do fmt.sbprint(buf, ":");
-        fmt.sbprint(buf, location.line);
-    }
+	if .Line in opts {
+		if Location_File_Opts & opts != nil || .Procedure in opts do fmt.sbprint(buf, ":");
+		fmt.sbprint(buf, location.line);
+	}
 
-    fmt.sbprint(buf, "] ");
+	fmt.sbprint(buf, "] ");
 }

+ 47 - 49
core/log/log.odin

@@ -2,18 +2,19 @@ package log
 
 import "core:runtime"
 import "core:fmt"
+import "core:sync"
 
 
 // NOTE(bill, 2019-12-31): These are defined in `package runtime` as they are used in the `context`. This is to prevent an import definition cycle.
 
 Level :: runtime.Logger_Level;
 /*
-Level :: enum {
-	Debug,
-	Info,
-	Warning,
-	Error,
-	Fatal,
+Logger_Level :: enum {
+	Debug   = 0,
+	Info    = 10,
+	Warning = 20,
+	Error   = 30,
+	Fatal   = 40,
 }
 */
 
@@ -67,64 +68,61 @@ Logger :: struct {
 }
 */
 
-Multi_Logger_Data :: struct {
-	loggers : []Logger,
+nil_logger_proc :: proc(data: rawptr, level: Level, text: string, options: Options, location := #caller_location) {
+	// Do nothing
 }
 
-create_multi_logger :: proc(logs: ..Logger) -> Logger {
-	data := new(Multi_Logger_Data);
-	data.loggers = make([]Logger, len(logs));
-	copy(data.loggers, logs);
-	return Logger{multi_logger_proc, data, Level.Debug, nil};
+nil_logger :: proc() -> Logger {
+	return Logger{nil_logger_proc, nil, Level.Debug, nil};
 }
 
-destroy_multi_logger :: proc(log : ^Logger) {
-	free(log.data);
-	log^ = nil_logger();
+// TODO(bill): Should these be redesigned so that they are do not rely upon `package fmt`?
+debugf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
+	logf(level=.Debug,   fmt_str=fmt_str, args=args, location=location);
 }
-
-multi_logger_proc :: proc(logger_data: rawptr, level: Level, text: string,
-                          options: Options, location := #caller_location) {
-	data := cast(^Multi_Logger_Data)logger_data;
-	if data.loggers == nil || len(data.loggers) == 0 {
-		return;
-	}
-	for log in data.loggers {
-		log.procedure(log.data, level, text, log.options, location);
-	}
+infof  :: proc(fmt_str: string, args: ..any, location := #caller_location) {
+	logf(level=.Info,    fmt_str=fmt_str, args=args, location=location);
 }
-
-nil_logger_proc :: proc(data: rawptr, level: Level, text: string, options: Options, location := #caller_location) {
-	// Do nothing
+warnf  :: proc(fmt_str: string, args: ..any, location := #caller_location) {
+	logf(level=.Warning, fmt_str=fmt_str, args=args, location=location);
+}
+errorf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
+	logf(level=.Error,   fmt_str=fmt_str, args=args, location=location);
+}
+fatalf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
+	logf(level=.Fatal,   fmt_str=fmt_str, args=args, location=location);
 }
 
-nil_logger :: proc() -> Logger {
-	return Logger{nil_logger_proc, nil, Level.Debug, nil};
+debug :: proc(args: ..any, location := #caller_location) {
+	log(level=.Debug,   args=args, location=location);
+}
+info  :: proc(args: ..any, location := #caller_location) {
+	log(level=.Info,    args=args, location=location);
+}
+warn  :: proc(args: ..any, location := #caller_location) {
+	log(level=.Warning, args=args, location=location);
+}
+error :: proc(args: ..any, location := #caller_location) {
+	log(level=.Error,   args=args, location=location);
+}
+fatal :: proc(args: ..any, location := #caller_location) {
+	log(level=.Fatal,   args=args, location=location);
 }
 
-// TODO(bill): Should these be redesigned so that they are do not rely upon `package fmt`?
-debugf :: proc(fmt_str : string, args : ..any, location := #caller_location) do logf(level=Level.Debug,   fmt_str=fmt_str, args=args, location=location);
-infof  :: proc(fmt_str : string, args : ..any, location := #caller_location) do logf(level=Level.Info,    fmt_str=fmt_str, args=args, location=location);
-warnf  :: proc(fmt_str : string, args : ..any, location := #caller_location) do logf(level=Level.Warning, fmt_str=fmt_str, args=args, location=location);
-errorf :: proc(fmt_str : string, args : ..any, location := #caller_location) do logf(level=Level.Error,   fmt_str=fmt_str, args=args, location=location);
-fatalf :: proc(fmt_str : string, args : ..any, location := #caller_location) do logf(level=Level.Fatal,   fmt_str=fmt_str, args=args, location=location);
-
-debug :: proc(args : ..any, location := #caller_location) do log(level=Level.Debug,   args=args, location=location);
-info  :: proc(args : ..any, location := #caller_location) do log(level=Level.Info,    args=args, location=location);
-warn  :: proc(args : ..any, location := #caller_location) do log(level=Level.Warning, args=args, location=location);
-error :: proc(args : ..any, location := #caller_location) do log(level=Level.Error,   args=args, location=location);
-fatal :: proc(args : ..any, location := #caller_location) do log(level=Level.Fatal,   args=args, location=location);
-
-log :: proc(level : Level, args : ..any, location := #caller_location) {
+log :: proc(level: Level, args: ..any, location := #caller_location) {
 	logger := context.logger;
-	if level < logger.lowest_level do return;
+	if level < logger.lowest_level {
+		return;
+	}
 	str := fmt.tprint(..args); //NOTE(Hoej): While tprint isn't thread-safe, no logging is.
 	logger.procedure(logger.data, level, str, logger.options, location);
 }
 
-logf :: proc(level : Level, fmt_str : string, args : ..any, location := #caller_location) {
+logf :: proc(level: Level, fmt_str: string, args: ..any, location := #caller_location) {
 	logger := context.logger;
-	if level < logger.lowest_level do return;
-	str := fmt.tprintf(fmt_str, ..args) if len(args) > 0 else fmt.tprint(fmt_str); //NOTE(Hoej): While tprint isn't thread-safe, no logging is.
+	if level < logger.lowest_level {
+		return;
+	}
+	str := fmt.tprintf(fmt_str, ..args);
 	logger.procedure(logger.data, level, str, logger.options, location);
 }

+ 5 - 5
core/runtime/core.odin

@@ -264,11 +264,11 @@ Allocator :: struct {
 // Logging stuff
 
 Logger_Level :: enum {
-	Debug,
-	Info,
-	Warning,
-	Error,
-	Fatal,
+	Debug   = 0,
+	Info    = 10,
+	Warning = 20,
+	Error   = 30,
+	Fatal   = 40,
 }
 
 Logger_Option :: enum {