Skip to main content

Querying GitHub Issues from Google App Script

I'm currently exploring different integrations that can be done between Google App Script and Git. This is part of a bigger attempt to integrate Git data into my project management system. I'll post more on that later. GitHub supports a number of very nice sub-systems. One of them is the GitHub Issues ticket tracking system. It's fairly robust and comes with GitHub - which means it's highly integrated out-of-the-box. Integration with Google's App Script is done via the fetchURL command and JSON object manipulation.  After a good bit of experimentation, I've settled on querying GitHub Issues with an "on open spreadsheet event" to avoid issues with Google's quota system. Essentially, Google prevents you from calling the fetchURL command more than X times (see the quota limits ) per day. That's not great if you have people actively working and changing data in a spreadsheet. Some of my other App Script routines are running thousands of times per d

Calendar Conversions

Has anyone tried to convert a Western-style calendar to either the Islamic or Hebrew calendar system? I've spent a bunch of time looking for a Pascal unit to do just that so I could include Muslim and Jewish holidays in my holiday class but haven't found any great resources. I finally found some C/C++ code that did the work and converted it over to Pascal. Keeping in mind that this is still a new conversion and that I didn't write the actual conversion logic, I'm publishing the code to help other would-be calendar converters. All of the conversion algorithms (and credit for them) are from Calendrical Calculations by Nachum Dershowitz and Edward Reingold.

I added the Day and Month name strings from various Google searches on things like Hebrew Month Names and Islamic Month Names, etc. I've compared the resulting output to both published calendars and to other conversion tools that do not provide their source. So far, I haven't seen any discrepancies other than some naming conventions. Apparently, Hebrew and Arab names are "open to interpretation" when you write them in Western languages. Feel free to change them to your particular dialect. Actually, I'd like to know what the differences are/could be/should be if someone wants to enlighten me. I don't speak either language and am relying on other translations to make this work.

Enjoy the code.



unit calconv;

interface
// The following Pascal code is translated from the Lisp code in
// ``Calendrical Calculations'' by Nachum Dershowitz and Edward M. Reingold,
// Software---Practice & Experience, vol. 20, no. 9 (September, 1990),
// pp. 899--928.

// This code is in the public domain, but any use of it
// should acknowledge its source.

// Classes GregorianDate, JulianDate, IslamicDate, and HebrewDate

// Translated from C++ / Lisp sources as published by Edward Reingold
// at http://emr.cs.iit.edu/~reingold/calendars/shtml

// Pascal translation by Marshall Fryman, 2008

uses sysutils;

type

TBaseDate = class
private
fYear:integer;
fMonth:integer;
fDay:integer;
public
class function cf_CalDateAsAbsDate(m,d,y:integer):integer; virtual; abstract;
class function DayName(d:integer):string; virtual; abstract;
class function LastDayOfMonth(m,y:integer):integer; virtual; abstract;
function CalDateAsAbsoluteDate:integer;
procedure AbsoluteDateToCalDate(absdate:integer); virtual; abstract;
property Year:integer read fYear;
property Month:integer read fMonth;
property Day:integer read fDay;
end;

TGregorianDate = class(TBaseDate)
// inherited from base
// fYear : integer; // 1...
// fMonth : integer; // 1 == January, ..., 12 == December
// fDay : integer; // 1..LastDayOfMonth(fMonth, fYear)
public
constructor Create(m,d,y:integer); overload; { fMonth = m; fDay = d; fYear = y; }
constructor Create(DT:TDateTime); overload;
constructor Create(absdate:integer); overload;
function DateAsText:string;
procedure AbsoluteDateToCalDate(absdate:integer); override;
class function cf_CalDateAsAbsDate(m,d,y:integer):integer; override;
class function DayName(d:integer):string; override;
class function MonthName(m:integer):string;
class function LastDayOfMonth(m,y:integer):integer; override;
end;

TJulianDate = class(TBaseDate)
// inherited from base
// int fYear; // 1...
// int fMonth; // 1 == January, ..., 12 == December
// int fDay; // 1..LastDayOfMonth(fMonth, fYear)
public
constructor Create(m,d,y:integer); overload; { fMonth = m; fDay = d; fYear = y; }
constructor Create(DT:TDateTime); overload;
constructor Create(absdate:integer); overload;
procedure AbsoluteDateToCalDate(absdate:integer); override;
class function cf_CalDateAsAbsDate(m,d,y:integer):integer; override;
class function DayName(d:integer):string; override;
class function MonthName(m:integer):string;
class function LastDayOfMonth(m,y:integer):integer; override;
end;

TIslamicDate = class(TBaseDate)
// inherited from base
// int fYear; // 1...
// int fMonth; // 1..12 (12 in a common Year)
// int fDay; // 1..LastDayOfMonth(fMonth,fYear)
public
constructor Create(m,d,y:integer); overload; { fMonth=m; fDay=d; fYear =y; }
constructor Create(DT:TDateTime); overload;
constructor Create(absdate:integer); overload;
function DateAsText:string;
procedure AbsoluteDateToCalDate(absdate:integer); override;
class function cf_CalDateAsAbsDate(m,d,y:integer):integer; override;
class function DayName(d:integer):string; override;
class function MonthName(m:integer):string;
class function LastDayOfMonth(m,y:integer):integer; override;
class function IsLeapYear(y:integer):boolean;
end;

THebrewDate = class(TBaseDate)
// inherited from base
// int fYear; // 1...
// int fMonth; // 1..LastMonthOfYear(fYear)
// int fDay; // 1..LastDayOfMonth(fMonth, fYear)
constructor Create(m,d,y:integer); overload; { fMonth=m; fDay=d; fYear =y; }
constructor Create(DT:TDateTime); overload;
constructor Create(absdate:integer); overload;
function DateAsText:string;
procedure AbsoluteDateToCalDate(absdate:integer); override;
class function cf_CalDateAsAbsDate(m,d,y:integer):integer; override;
class function DayName(d:integer):string; override;
class function MonthName(m,y:integer):string;
class function LastDayOfMonth(m,y:integer):integer; override;
class function IsLeapYear(y:integer):boolean;
class function LastMonthOfYear(y:integer):integer;
class function ShortKislev(y:integer):boolean;
class function LongHeshvan(y:integer):boolean;
class function DaysInYear(y:integer):integer;
class function HebrewCalendarElapsedDays(y:integer):integer;
end;

implementation

// Absolute dates

// "Absolute date" means the number of days elapsed since the Gregorian date
// Sunday, December 31, 1 BC. (Since there was no fYear 0, the fYear following
// 1 BC is 1 AD.) Thus the Gregorian date January 1, 1 AD is absolute date
// number 1.

const
JulianEpoch = -2; // Absolute date of start of Julian calendar
IslamicEpoch = 227014; // Absolute date of start of Islamic calendar
HebrewEpoch = -1373429; // Absolute date of start of Hebrew calendar



// Absolute date of the x-fDay on or before absolute date d.
// x=0 means Sunday, x=1 means Monday, and so on.
function XdayOnOrBefore(d,x:integer):integer;
begin
result:=(d - ((d - x) mod 7));
end;



{ TGregorianDate }

constructor TGregorianDate.Create(m,d,y:integer);
begin
fMonth :=m;
fDay :=d;
fYear :=y;
end;

// Computes the Gregorian date from the absolute date
constructor TGregorianDate.Create(absdate:integer);
begin
AbsoluteDateToCalDate(absdate);
end;


// Computes the absolute date from the Gregorian date.
constructor TGregorianDate.Create(DT: TDateTime);
var y,m,d:word;
begin
DecodeDate(DT,y,m,d);
fYear:=y;
fMonth:=m;
fDay:=d;
end;

procedure TGregorianDate.AbsoluteDateToCalDate(absdate: integer);
begin
// Search forward fYear by fYear from approximate fYear
fYear := absdate div 366;
while (absdate >= TGregorianDate.cf_CalDateAsAbsDate(1,1,fYear+1)) do
inc(fYear);
// Search forward fMonth by fMonth from January
fMonth := 1;
while (absdate > TGregorianDate.cf_CalDateAsAbsDate(fMonth, LastDayOfMonth(fMonth,fYear), fYear)) do
inc(fMonth);
fDay := absdate - TGregorianDate.cf_CalDateAsAbsDate(fMonth,1,fYear) + 1;
end;

class function TGregorianDate.cf_CalDateAsAbsDate(m,d,y:integer):integer;
var iD,iM:integer;
begin
iD := d; // days this fMonth
for iM := m - 1 downto 1 do // days in prior months this fYear
iD := iD + LastDayOfMonth(iM, y);
result:=(iD // days this fYear
+ 365 * (y - 1) // days in previous years ignoring leap days
+ (y - 1) div 4 // Julian leap days before this fYear...
- (y - 1) div 100 // ...minus prior century years...
+ (y - 1) div 400); // ...plus prior years divisible by 400
end;

function TGregorianDate.DateAsText: string;
begin
result := DayName(CalDateAsAbsoluteDate mod 7)+', '+MonthName(Month)+' '+IntToStr(Day)+', '+IntToStr(Year);
end;

class function TGregorianDate.DayName(d: integer): string;
begin
if d>6 then d:=d mod 7;
case d of
0 : result:='Sunday';
1 : result:='Monday';
2 : result:='Tuesday';
3 : result:='Wednesday';
4 : result:='Thursday';
5 : result:='Friday';
6 : result:='Saturday';
else
result:='Invalid Day';
end;
end;

// Compute the last date of the fMonth for the Gregorian calendar.
class function TGregorianDate.LastDayOfMonth(m, y: integer): integer;
begin
result:=31;
case m of
2: if ((((y mod 4) = 0) and ((y mod 100) <>0)) OR ((y mod 400) = 0)) then
result:= 29
else
result:= 28;
4,
6,
9,
11: result := 30;
end;
end;

class function TGregorianDate.MonthName(m: integer): string;
begin
case m of
1 : result := 'January';
2 : result := 'February';
3 : result := 'March';
4 : result := 'April';
5 : result := 'May';
6 : result := 'June';
7 : result := 'July';
8 : result := 'August';
9 : result := 'September';
10 : result := 'October';
11 : result := 'November';
12 : result := 'December';
else
result:='Invalid Month';
end;
end;

{ TJulianDate }

constructor TJulianDate.Create(m, d, y: integer);
begin
fmonth := m;
fday := d;
fyear := y;
end;

// Computes the Julian date from the absolute date.
constructor TJulianDate.Create(absdate: integer);
begin
AbsoluteDateToCalDate(absdate);
end;

// Computes the absolute date from the Julian date.
constructor TJulianDate.Create(DT: TDateTime);
var gd:TGregorianDate;
begin
gd:=TGregorianDate.Create(DT);
AbsoluteDateToCalDate(gd.CalDateAsAbsoluteDate);
gd.Free;
end;

procedure TJulianDate.AbsoluteDateToCalDate(absdate: integer);
begin
// Search forward fYear by fYear from approximate fYear
fYear := (absdate + JulianEpoch) div 366;
while (absdate >= TJulianDate.cf_CalDateAsAbsDate(1,1,fYear+1)) do
inc(fYear);
// Search forward fMonth by fMonth from January
fMonth := 1;
while (absdate > TJulianDate.cf_CalDateAsAbsDate(fMonth, LastDayOfMonth(fMonth,fYear), fYear)) do
inc(fMonth);
fDay := absdate - TJulianDate.cf_CalDateAsAbsDate(fMonth,1,fYear) + 1;
end;

class function TJulianDate.cf_CalDateAsAbsDate(m, d, y: integer): integer;
var iD, iM:integer;
begin
iD:=d; // days this Month
for iM:=m-1 downto 1 do // days in prior months this Year
iD := iD + LastDayOfMonth(m, y);
result := (iD // days this fYear
+ 365 * (y - 1) // days in previous years ignoring leap days
+ (y - 1) div 4 // leap days before this Year...
+ JulianEpoch); // days elapsed before absolute date 1

end;

class function TJulianDate.DayName(d: integer): string;
begin
if d>6 then d:=d mod 7;

case d of
0 : result:='Sunday';
1 : result:='Monday';
2 : result:='Tuesday';
3 : result:='Wednesday';
4 : result:='Thursday';
5 : result:='Friday';
6 : result:='Saturday';
else
result:='Invalid Day';
end;
end;

// Compute the last date of the fMonth for the Julian calendar.
class function TJulianDate.LastDayOfMonth(m, y: integer): integer;
begin
case m of
2: if ((y mod 4) = 0) then
result := 29
else
result := 28;
4,
6,
9,
11: result := 30;
else result := 31;
end; {of case}
end;

class function TJulianDate.MonthName(m: integer): string;
begin
case m of
1 : result := 'January';
2 : result := 'February';
3 : result := 'March';
4 : result := 'April';
5 : result := 'May';
6 : result := 'June';
7 : result := 'July';
8 : result := 'August';
9 : result := 'September';
10 : result := 'October';
11 : result := 'November';
12 : result := 'December';
else
result:='Invalid Month';
end;
end;

{ TIslamicDate }

constructor TIslamicDate.Create(m, d, y: integer);
begin
fmonth := m;
fday := d;
fyear := y;
end;

// Computes the Islamic date from the absolute date.
constructor TIslamicDate.Create(absdate: integer);
begin
AbsoluteDateToCalDate(absdate);
end;

procedure TIslamicDate.AbsoluteDateToCalDate(absdate: integer);
begin
if (absdate <= IslamicEpoch) then // Date is pre-Islamic
begin
fMonth := 0;
fDay := 0;
fYear := 0;
end
else
begin
// Search forward fYear by fYear from approximate fYear
fYear := (absdate - IslamicEpoch) div 355;
while (absdate >= TIslamicDate.cf_CalDateAsAbsDate(1,1,fYear+1)) do
inc(fYear);
// Search forward fMonth by fMonth from Muharram
fMonth := 1;
while (absdate > TIslamicDate.cf_CalDateAsAbsDate(fMonth, LastDayOfMonth(fMonth,fYear), fYear)) do
inc(fMonth);
fDay := absdate - TIslamicDate.cf_CalDateAsAbsDate(fMonth,1,fYear) + 1;
end;
end;

class function TIslamicDate.cf_CalDateAsAbsDate(m, d, y: integer): integer;
begin
result := (d // days so far this fMonth
+ 29 * (m - 1) // days so far...
+ m div 2 // ...this fYear
+ 354 * (y - 1) // non-leap days in prior years
+ (3 + (11 * y)) div 30 // leap days in prior years
+ IslamicEpoch); // days before start of calendar

end;

constructor TIslamicDate.Create(DT: TDateTime);
var gd:TGregorianDate;
begin
gd:=TGregorianDate.Create(DT);
AbsoluteDateToCalDate(gd.CalDateAsAbsoluteDate);
gd.Free;
end;

function TIslamicDate.DateAsText: string;
begin
result := DayName(Day)+', '+MonthName(Month)+' '+IntToStr(Day)+', '+IntToStr(Year);
end;

class function TIslamicDate.DayName(d: integer): string;
begin
if d>6 then d:=d mod 7;
case d of
0 : result := 'As-Sabt';
1 : result := 'Al-Ahad';
2 : result := 'Al-`ithnayn';
3 : result := 'Ath-Thulatha';
4 : result := 'Al-`Arba`aa';
5 : result := 'Al-Khamees';
6 : result := 'Al-Jum`ah';
else result:='Invalid Day';
end;
end;

// True if fYear is an Islamic leap fYear
class function TIslamicDate.IsLeapYear(y: integer): boolean;
begin
result:=((((11 * y) + 14) mod 30) < 11);
end;

// Last Day in fMonth during fYear on the Islamic calendar.
class function TIslamicDate.LastDayOfMonth(m, y: integer): integer;
begin
if (((m mod 2) = 1) OR ((m = 12) and IsLeapYear(y))) then
result:=30
else
result:=29;
end;

class function TIslamicDate.MonthName(m: integer): string;
begin
case m of
1: result := 'Muharram';
2: result := 'Safar';
3: result := 'Rabi`al-Awwal';
4: result := 'Rabi`ath-Thani';
5: result := 'Jumada l-Ula';
6: result := 'Jumada t=Tania';
7: result := 'Rajab';
8: result := 'Sha`ban';
9: result := 'Ramadan';
10: result := 'Shawwal';
11: result := 'Dhul `l-Qa`da';
12: result := 'Dhul `l-Hijja';
else result:='Invalid Month';
end;
end;

{ THebrewDate }

constructor THebrewDate.Create(m, d, y: integer);
begin
fmonth := m;
fday := d;
fyear := y;
end;

// Computes the Hebrew date from the absolute date.
constructor THebrewDate.Create(absdate: integer);
begin
AbsoluteDateToCalDate(absdate);
end;

procedure THebrewDate.AbsoluteDateToCalDate(absdate: integer);
begin
fYear := (absdate + HebrewEpoch) div 366; // Approximation from below.
// Search forward for fYear from the approximation.
while (absdate >= THebrewDate.cf_CalDateAsAbsDate(7,1,fYear + 1)) do
inc(fYear);
// Search forward for month from either Tishri or Nisan.
if (absdate < THebrewDate.cf_CalDateAsAbsDate(1, 1, fYear)) then
fMonth := 7 // Start at Tishri
else
fMonth := 1; // Start at Nisan
while (absdate > THebrewDate.cf_CalDateAsAbsDate(fMonth, (LastDayOfMonth(fMonth,fYear)), fYear)) do
inc(fMonth);
// Calculate the fDay by subtraction.
fDay := absdate - THebrewDate.cf_CalDateAsAbsDate(fMonth, 1, fYear) + 1;
end;

class function THebrewDate.cf_CalDateAsAbsDate(m, d, y: integer): integer;
var DayInYear:integer;
iM:integer;
begin
DayInYear := d; // Days so far this Month.
if (m < 7) then // Before Tishri, so add days in prior months
begin // this Year before and after Nisan.
iM := 7;
while (iM <= (LastMonthOfYear(y))) do
begin
DayInYear := DayInYear + LastDayOfMonth(iM, y);
inc(iM);
end;
iM := 1;
while (iM < m) do
begin
DayInYear := DayInYear + LastDayOfMonth(iM, y);
inc(iM);
end;
end
else // Add days in prior months this Year
begin
iM := 7;
while (iM < m) do
begin
DayInYear := DayInYear + LastDayOfMonth(iM, y);
inc(iM);
end;
end;

result := (DayInYear +
(HebrewCalendarElapsedDays(y)// Days in prior years.
+ HebrewEpoch)); // Days elapsed before absolute date 1.
end;

constructor THebrewDate.Create(DT: TDateTime);
var gd:TGregorianDate;
begin
gd:=TGregorianDate.Create(DT);
AbsoluteDateToCalDate(gd.CalDateAsAbsoluteDate);
gd.Free;
end;

function THebrewDate.DateAsText: string;
begin
result := DayName(Day)+', '+MonthName(Month,Year)+' '+IntToStr(Day)+', '+IntToStr(Year);
end;

class function THebrewDate.DayName(d: integer): string;
begin
if d>6 then d:=d mod 7;
case d of
0 : result := 'Yom Ree-Shoun';
1 : result := 'Yom She-Nee';
2 : result := 'Yom Shelee-She';
3 : result := 'Yom Re-Ve-ee';
4 : result := 'Yom Hah-Mee-Shee';
5 : result := 'Yom Shee-Shee';
6 : result := 'Yom Sha-Bat';
else result := 'Invalid Day';
end;
end;

// Number of days in Hebrew Year.
class function THebrewDate.DaysInYear(y: integer): integer;
begin
result := ((HebrewCalendarElapsedDays(y + 1)) -
(HebrewCalendarElapsedDays(y)));
end;

// Number of days elapsed from the Sunday prior to the start of the
// Hebrew calendar to the mean conjunction of Tishri of Hebrew fYear.
class function THebrewDate.HebrewCalendarElapsedDays(y: integer): integer;
var MonthsElapsed,
PartsElapsed,
HoursElapsed,
ConjunctionDay,
ConjunctionParts,
AlternativeDay : integer;
begin
MonthsElapsed :=
(235 * ((y - 1) div 19)) // Months in complete cycles so far.
+ (12 * ((y - 1) mod 19)) // Regular months in this cycle.
+ (7 * ((y - 1) mod 19) + 1) div 19; // Leap months this cycle
PartsElapsed := 204 + (793 * (MonthsElapsed mod 1080));
HoursElapsed :=
5 + (12 * MonthsElapsed) + (793 * (MonthsElapsed div 1080))
+ (PartsElapsed div 1080);
ConjunctionDay := 1 + (29 * MonthsElapsed) + (HoursElapsed div 24);
ConjunctionParts := (1080 * (HoursElapsed mod 24)) + (PartsElapsed mod 1080);
if ((ConjunctionParts >= 19440) // If new moon is at or after midday,
OR (((ConjunctionDay mod 7) = 2) // ...or is on a Tuesday...
and (ConjunctionParts >= 9924) // at 9 hours, 204 parts or later...
and not (IsLeapYear(y))) // ...of a common year,
OR (((ConjunctionDay mod 7) = 1) // ...or is on a Monday at...
and (ConjunctionParts >= 16789) // 15 hours, 589 parts or later...
and (IsLeapYear(y - 1)))) then // at the end of a leap year
// Then postpone Rosh HaShanah one Day
AlternativeDay := ConjunctionDay + 1
else
AlternativeDay := ConjunctionDay;
if (((AlternativeDay mod 7) = 0) // If Rosh HaShanah would occur on Sunday,
OR ((AlternativeDay mod 7) = 3) // or Wednesday,
OR ((AlternativeDay mod 7) = 5)) then // or Friday
// Then postpone it one (more) Day
result := (1 + AlternativeDay)
else
result := AlternativeDay;
end;

// True if y is an Hebrew leap year
class function THebrewDate.IsLeapYear(y: integer): boolean;
begin
result := ((((7 * y) + 1) mod 19) < 7);
end;

// Last fDay of Month in Hebrew Year.
class function THebrewDate.LastDayOfMonth(m, y: integer): integer;
begin
if ((m = 2)
OR (m = 4)
OR (m = 6)
OR ((m = 8) and not (LongHeshvan(y)))
OR ((m = 9) and ShortKislev(y))
OR (m = 10)
OR ((m = 12) and not (IsLeapYear(y)))
OR (m = 13)) then
result := 29
else
result:= 30;

end;

// Last Month of Hebrew Year y.
class function THebrewDate.LastMonthOfYear(y: integer): integer;
begin
if (IsLeapYear(y)) then
result := 13
else
result := 12;
end;

// True if Heshvan is long in Hebrew fYear.
class function THebrewDate.LongHeshvan(y: integer): boolean;
begin
result := ((DaysInYear(y) mod 10) = 5);
end;

class function THebrewDate.MonthName(m,y: integer): string;
begin
result:='Invalid Month';
if not IsLeapYear(y) then
case m of
1 : result := 'Nissan';
2 : result := 'Iyar';
3 : result := 'Sivan';
4 : result := 'Tammuz';
5 : result := 'Av';
6 : result := 'Elul';
7 : result := 'Tishrei';
8 : result := 'Heshvan';
9 : result := 'Kislev';
10: result := 'Teves';
11: result := 'Shevat';
12: result := 'Adar';
end
else
case m of
1 : result := 'Nissan';
2 : result := 'Iyar';
3 : result := 'Sivan';
4 : result := 'Tammuz';
5 : result := 'Av';
6 : result := 'Elul';
7 : result := 'Tishrei';
8 : result := 'Heshvan';
9 : result := 'Kislev';
10: result := 'Teves';
11: result := 'Shevat';
12: result := 'Adar I';
13: result := 'Adar II';
end
end;

// True if Kislev is short in Hebrew fYear.
class function THebrewDate.ShortKislev(y: integer): boolean;
begin
result := ((DaysInYear(y) mod 10) = 3);
end;

{ TBaseDate }

function TBaseDate.CalDateAsAbsoluteDate: integer;
begin
result := self.cf_CalDateAsAbsDate(Month,Day,Year);
end;

end.

Comments

Popular posts from this blog

SMTP Mail and Indy (again)

Having spent a lot of time recently working on a ping scanner using Indy, I noticed that there's a lot of questions still on using SMTP with Indy. Let me first say that I am not an Indy expert. I get along with it successfully but find I still have to research things frequently. With the disclaimer out of the way, we can get to the offering. A while back I wrote a handy little unit to simply send a mail message with or without attachments and with or without providing authentication. It even has support for OpenSSL. I use this unit in a number of applications and have seen it successfully send hundreds of e-mails without issue. I recently added support for threaded message sending to take advantage of the multi-core system I'm now running on. This code has had a few additions (like the logger) that I've gleaned over time from various newsgroup postings, but I didn't record the authors so let me credit the anonymous Internet authors who support Indy. It's really amaz

Detecting a virtualized environment

CubicDesign on delphi-talk.elists.org recently asked the question: "How do I know/detect if my software is running under Windows [or a virtual environment]?" Well, it turns out that it's a lot harder to tell than you would think. Apparently, the VM (VMware, Xen, Wine, etc.) doesn't really want you to be able to do this. At least not easily. For VMware, there is a decent little C routine called jerry.c that does the trick. Jerry actually uses a simple communication channel that VMware left open. It's not 100% foolproof since the admin can change the channel, but that's not likely going to happen unless the system is specifically designed to be a honeypot. If you're running on a honeypot and still have a legitimate reason for detection, you could look at the much more complex scoopy implementation which inspects how the system is actually virtualized using the SIDT CPU instruction instead of a communication channel. Another reference (red pill) is here . F

Delphi Case with Strings

Zarko Gajic posted about this topic on his Delphi Tips recently showing how one could use a case statement with strings. His solution basically passes in an array on the stack and then iterates through it providing the index number of the matching string. I don't often want to do this, but the idea comes up occassionally enough that I thought I'd play with it a little. The first thing that struck me with this is that passing things on the stack is bound to be slow. Any time you can avoid memory allocation in your routines, do it. The way Zarko wrote his StringToCaseSelect routine created a COPY of the information on the stack. In my testing, just changing the CaseList: array of string to CaseList:const array of string improved the performance of the code by almost 30% for his example. Mind, I'm not using hyper-precise counters; however, it definitely makes a difference. Secondly, I was curious how the performance changed if I used the old stand-by: If then else. Using the

Copyright 2008-2022, Marshall Fryman