6 using System
.Runtime
.CompilerServices
;
7 using System
.Runtime
.InteropServices
;
13 class LogcatTextWriter
: TextWriter
{
15 const string LibLog
= "/system/lib/liblog.so";
16 const string LibLog64
= "/system/lib64/liblog.so";
18 readonly byte[] appname
;
21 StringBuilder line
= new StringBuilder ();
23 public LogcatTextWriter (string appname
, TextWriter stdout
)
25 this.appname
= Encoding
.UTF8
.GetBytes (appname
+ '\0');
29 public override Encoding Encoding
{
30 get {return Encoding.UTF8;}
33 public override void Write (string s
)
40 public override void Write (char value)
48 public override void WriteLine ()
50 var o
= line
.ToString ();
57 void Log (string message
)
59 const int buffer_size
= 512;
62 if (Encoding
.UTF8
.GetByteCount (message
) < buffer_size
) {
64 fixed (char *b_message
= message
) {
65 byte* buffer
= stackalloc byte[buffer_size
];
66 int written
= Encoding
.UTF8
.GetBytes (b_message
, message
.Length
, buffer
, buffer_size
- 1);
67 buffer
[written
] = (byte)'\0';
73 } catch (ArgumentException
) {
74 /* It might be due to a failure to encode a character, or due to a smaller than necessary buffer. In the
75 * secode case, we want to fallback to simply allocating on the heap. */
79 using (SafeStringMarshal str
= new SafeStringMarshal(message
)) {
80 Log ((byte*) str
.Value
);
85 unsafe void Log (byte* b_message
)
87 fixed (byte *b_appname
= appname
) {
88 Log (b_appname
, 1 << 5 /* G_LOG_LEVEL_MESSAGE */, b_message
);
92 public static bool IsRunningOnAndroid ()
94 return File
.Exists (LibLog
) || File
.Exists (LibLog64
);
97 [MethodImpl(MethodImplOptions
.InternalCall
)]
98 static unsafe extern void Log (byte *appname
, int level
, byte *message
);