Browse Source

+ implemented SysUtils.FileGetDate for WASI

Nikolay Nikolov 3 years ago
parent
commit
8f95c14827
2 changed files with 140 additions and 12 deletions
  1. 12 12
      rtl/objpas/sysutils/dati.inc
  2. 128 0
      rtl/wasi/sysutils.pp

+ 12 - 12
rtl/objpas/sysutils/dati.inc

@@ -1258,7 +1258,7 @@ Var YY,MM,DD,H,m,s,msec : Word;
 begin
   Decodedate (DateTime,YY,MM,DD);
   DecodeTime (DateTime,h,m,s,msec);
-{$ifndef unix}
+{$if not defined(unix) and not defined(wasi)}
   If (YY<1980) or (YY>2099) then
     Result:=0
   else
@@ -1266,24 +1266,24 @@ begin
     Result:=(s shr 1) or (m shl 5) or (h shl 11);
     Result:=Result or longint(DD shl 16 or (MM shl 21) or (word(YY-1980) shl 25));
     end;
-{$else unix}
+{$else unix or wasi}
   Result:=LocalToEpoch(yy,mm,dd,h,m,s);
-{$endif unix}
+{$endif unix or wasi}
 end;
 
 Function UniversalToFileDate(DateTime : TDateTime) : int64;
-{$ifndef unix}
+{$if not defined(unix) and not defined(wasi)}
 begin
   Result := DateTimeToFileDate(UniversalTimeToLocal(DateTime));
 end;
-{$else unix}
+{$else unix or wasi}
 Var YY,MM,DD,H,m,s,msec : Word;
 begin
   Decodedate (DateTime,YY,MM,DD);
   DecodeTime (DateTime,h,m,s,msec);
   Result:=UniversalToEpoch(yy,mm,dd,h,m,s);
 end;
-{$endif unix}
+{$endif unix or wasi}
 
 function CurrentYear: Word;
 var
@@ -1295,7 +1295,7 @@ end;
 
 Function FileDateToDateTime (Filedate : Int64) : TDateTime;
 
-{$ifndef unix}
+{$if not defined(unix) and not defined(wasi)}
 Var Date,Time : Word;
 
 begin
@@ -1304,29 +1304,29 @@ begin
   Result:=ComposeDateTime(EncodeDate((Date shr 9) + 1980,(Date shr 5) and 15, Date and 31),
           EncodeTime(Time shr 11, (Time shr 5) and 63, (Time and 31) shl 1,0));
 end;
-{$else unix}
+{$else unix or wasi}
 var
   y, mon, d, h, min, s: word;
 begin
   EpochToLocal(FileDate,y,mon,d,h,min,s);
   Result:=ComposeDateTime(EncodeDate(y,mon,d),EncodeTime(h,min,s,0));
 end;
-{$endif unix}
+{$endif unix or wasi}
 
 Function FileDateToUniversal (Filedate : Int64) : TDateTime;
 
-{$ifndef unix}
+{$if not defined(unix) and not defined(wasi)}
 begin
   Result := LocalTimeToUniversal(FileDateToDateTime(Filedate));
 end;
-{$else unix}
+{$else unix or wasi}
 var
   y, mon, d, h, min, s: word;
 begin
   EpochToUniversal(FileDate,y,mon,d,h,min,s);
   Result:=ComposeDateTime(EncodeDate(y,mon,d),EncodeTime(h,min,s,0));
 end;
-{$endif unix}
+{$endif unix or wasi}
 
 function TryStrToDate(const S: ShortString; out Value: TDateTime): Boolean;
 begin

+ 128 - 0
rtl/wasi/sysutils.pp

@@ -51,6 +51,126 @@ implementation
 
 {$DEFINE executeprocuni} (* Only 1 byte version of ExecuteProcess is provided by the OS *)
 
+Function UniversalToEpoch(year,month,day,hour,minute,second:Word):int64;
+const
+  days_in_month: array [boolean, 1..12] of Byte =
+    ((31,28,31,30,31,30,31,31,30,31,30,31),
+     (31,29,31,30,31,30,31,31,30,31,30,31));
+  days_before_month: array [boolean, 1..12] of Byte =
+    ((0,
+      0+31,
+      0+31+28,
+      0+31+28+31,
+      0+31+28+31+30,
+      0+31+28+31+30+31,
+      0+31+28+31+30+31+30,
+      0+31+28+31+30+31+30+31,
+      0+31+28+31+30+31+30+31+31,
+      0+31+28+31+30+31+30+31+31+30,
+      0+31+28+31+30+31+30+31+31+30+31,
+      0+31+28+31+30+31+30+31+31+30+31+30),
+     (0,
+      0+31,
+      0+31+29,
+      0+31+29+31,
+      0+31+29+31+30,
+      0+31+29+31+30+31,
+      0+31+29+31+30+31+30,
+      0+31+29+31+30+31+30+31,
+      0+31+29+31+30+31+30+31+31,
+      0+31+29+31+30+31+30+31+31+30,
+      0+31+29+31+30+31+30+31+31+30+31,
+      0+31+29+31+30+31+30+31+31+30+31+30));
+var
+  leap: Boolean;
+  days_in_year: LongInt;
+  y,m: LongInt;
+begin
+  if (year<1970) or (month<1) or (month>12) or (day<1) or (day>31) or
+     (hour>=24) or (minute>=60) or (second>=60) then
+  begin
+    result:=-1;
+    exit;
+  end;
+  leap:=((year mod 4)=0) and (((year mod 100)<>0) or ((year mod 400)=0));
+  if day>days_in_month[leap,month] then
+  begin
+    result:=-1;
+    exit;
+  end;
+  result:=0;
+  for y:=1970 to year-1 do
+    if ((y mod 4)=0) and (((y mod 100)<>0) or ((y mod 400)=0)) then
+      Inc(result,366)
+    else
+      Inc(result,365);
+  Inc(result,days_before_month[leap,month]);
+  Inc(result,day-1);
+  result:=(((result*24+hour)*60+minute)*60)+second;
+end;
+
+Function LocalToEpoch(year,month,day,hour,minute,second:Word):int64;
+begin
+  { todo: convert UTC to local time, as soon as we can get the local timezone
+    from WASI: https://github.com/WebAssembly/WASI/issues/239 }
+  result:=UniversalToEpoch(year,month,day,hour,minute,second);
+end;
+
+Procedure EpochToUniversal(epoch:int64;var year,month,day,hour,minute,second:Word);
+const
+  days_in_month: array [boolean, 1..12] of Byte =
+    ((31,28,31,30,31,30,31,31,30,31,30,31),
+     (31,29,31,30,31,30,31,31,30,31,30,31));
+var
+  leap: Boolean;
+  days_in_year: LongInt;
+begin
+  if epoch<0 then
+  begin
+    year:=0;
+    month:=0;
+    day:=0;
+    hour:=0;
+    minute:=0;
+    second:=0;
+    exit;
+  end;
+  second:=epoch mod 60;
+  epoch:=epoch div 60;
+  minute:=epoch mod 60;
+  epoch:=epoch div 60;
+  hour:=epoch mod 24;
+  epoch:=epoch div 24;
+  year:=1970;
+  leap:=false;
+  days_in_year:=365;
+  while epoch>=days_in_year do
+  begin
+    Dec(epoch,days_in_year);
+    Inc(year);
+    leap:=((year mod 4)=0) and (((year mod 100)<>0) or ((year mod 400)=0));
+    if leap then
+      days_in_year:=366
+    else
+      days_in_year:=365;
+  end;
+  month:=1;
+  Inc(epoch);
+  while epoch>days_in_month[leap,month] do
+  begin
+    Dec(epoch,days_in_month[leap,month]);
+    Inc(month);
+  end;
+  day:=Word(epoch);
+end;
+
+Procedure EpochToLocal(epoch:int64;var year,month,day,hour,minute,second:Word);
+begin
+  { todo: convert UTC to local time, as soon as we can get the local timezone
+    from WASI: https://github.com/WebAssembly/WASI/issues/239 }
+  EpochToUniversal(epoch,year,month,day,hour,minute,second);
+end;
+
 { Include platform independent implementation part }
 {$i sysutils.inc}
 
@@ -324,7 +444,15 @@ end;
 
 
 Function FileGetDate (Handle : THandle) : Int64;
+var
+  res: __wasi_errno_t;
+  Info: __wasi_filestat_t;
 begin
+  res:=__wasi_fd_filestat_get(Handle,@Info);
+  if res=__WASI_ERRNO_SUCCESS then
+    result:=Info.mtim div 1000000000
+  else
+    result:=-1;
 end;