Code Monkey home page Code Monkey logo

envvars's People

Contributors

delphidabbler avatar

Watchers

 avatar

Forkers

atkins126 loop80

envvars's Issues

Add class properties to TPJEnvironmentVars

The component provides the Values[] property that is indexed by env var name. Although TPJEnvironmentVars has get and set methods that provide the same functionality, maybe a similar class property that provides a familiar interface would be useful.

Additionally, would a read only Names[] class property (with integer index) be useful too?

Encapsulate an environment block in a class

I really don't like how messy the TPJEnvironmentVars.CreateBlock method is.

It would be much better to encapsulate the whole messy business in a separate class and provide a Memory property that points to the required block.

TPJEnvironmentVars.CreateBlock could then be overridden to accept this new object as a parameter if it was thought necessary to retain such a method. The old TPJEnvironmentVars.CreateBlock could then be deprecated.

Add enumerator overloads with no Data parameter.

Although the Data parameter of the various TPJEnvironmentVars enumerator methods is useful on occasion, a lot of the time it isn't required.

So how about a couple more enumerator overloads without the Data parameter? E.g.:

TPJEnvironmentVars = class(TObject)
// ...
public 
  // ...
  type
    TEnumNamesCallback = reference to procedure (const VarName: string);
    TEnumVarsCallback = reference to procedure(const EnvVar: TPJEnvironmentVar);
    //.. 
  class procedure EnumNames(Callback: TEnumNamesCallback); overload;
  class procedure EnumVars(Callback: TEnumVarsCallback); overload;
  // ...
end;

// ...

class procedure TPJEnvironmentVars.EnumNames(Callback: TEnumNamesCallback)
begin
  Assert(Assigned(Callback));
  EnumNames<Integer>(
    procedure (const VarName: string; Data: Integer)
    begin
      Callback(VarName);
    end,
    0 // Dummy value
  );
end;

class procedure TPJEnvironmentVars.EnumVars(Callback: TEnumVarsCallback)
begin
  Assert(Assigned(Callback));
  EnumVars<Integer>(
    procedure (const EnvVar: TPJEnvironmentVar; Data: Integer)
    begin
      Callback(EnvVar);
    end,
    0 // Dummy value
  );
end;

Remove deprecated functions

Like the component mentioned in issue #1, there are several deprecated functions in the unit that it's really time to remove

Make TPJEnvironmentVar record read only / invariant.

There's no need for the user to change any fields of TPJEnvironmentVar, so we can make the record invariant by hiding the fields, adding read only properties and providing a constructor:

TPJEnvironmentVar = record
strict private
  var
    fName: string;
    fValue: string;
public
  constructor Create(const AName, AValue: string);
  ///  <summary>Environment variable name.</summary>
  property Name: string read fName;
  ///  <summary>Environment variable value.</summary>
  property Value: string read fValue;
end;

The constructor will have have the obvious simple implementation.

Wherever the records fields are directly set in the code the constructor will need to be called instead.

Add mapping and selection methods to TPJEnvironmentVars

Mapping and selection methods are often useful.

The mapping would transform each environment variable to some type T and create an array of T the same size as there are environment variables.

The selection method would select 0 or many environment variables and return an array containing them.

Both would use callbacks that are passed the environment variable and possibly the index and some data passed in by the user.

The mapping callback will return a value of the required type while the selection will return Boolean true to select the environment variable and false to exclude it.

Potential problem with ANSI environment blocks & `TPJEnvironmentVars.GetAll`

Unicode environment blocks are distinguished when calling CreateProcess by passing the CREATE_UNICODE_ENVIRONMENT flag.

This raises the question of whether we can rely upon a process' environment block being Unicode? All processes that I've seen launched from modern Windows have Unicode environment blocks, but what about child processes explicitly launched with ANSI environment blocks? Does Windows convert them to Unicode before the process is started?

This is very important to know because the TPJEnvironmentVars.GetAll method assumes that its host process has a Unicode environment block and will fail if the block is ANSI. Therefore TPJEnvironmentVars.GetAll will fail on any process that has an ANSI environment block. That would be a major bug.

Given that Windows knows an environment block is Unicode because of the CREATE_UNICODE_ENVIRONMENT flag, is there a way testing for that flag? Note that this is only important if Windows doesn't convert ANSI environment blocks to Unicode.

Tests are required.

Originally posted by @delphidabbler in #12 (comment)

Add templated enumerator methods & callbacks to TPJEnvironmentVars

At present there are two enumerator methods of TPJEnvironmentVars:

class procedure EnumNames(Callback: TPJEnvVarsEnum; Data: Pointer);
class procedure EnumVars(Callback: TPJEnvVarsEnumEx; Data: Pointer);

As can be seen these enumerators are passed data in the traditional way, as a pointer. Often the pointer would be cast to an object on an integer, which isn't type safe.

How about adding some templated overloaded methods like these:

class procedure EnumNames<T>(Callback: TPJEnvVarsEnum<T>; Data: T);
class procedure EnumVars<T>(Callback: TPJEnvVarsEnumEx<T>; Data: T);

We will need new enumerator types:

TPJEnvVarsEnum<T> =  reference to procedure(const VarName: string; Data: T);
TPJEnvVarsEnum<T> =  reference to procedure(const EnvVar: TPJEnvironmentVar; Data: T);

The original methods and callback types could be deprecated.

Add a method to parse a given environment block

The TPJEnvironmentVars.GetAll method parses the current environment block. There is also similar code in demo1 that parses a generated block.

Between the two there's enough code to create a suitable method. TPJEnvironmentVars.GetAll could then be rewritten to use the new method to parse the current environment block.

Move enumerator callback types into TPJEnvironmentVars

Once the component is removed (issue #1) the enumerator callback type definitions apply only to TPJEnvironmentVars. It would therefore make sense to move them inside the class. We could also take the opportunity to rename them. E.g.

type
  TPJEnvironmentVars = class(TObject)
  // ...
  public
    type
      TEnumNamesCallback = reference to procedure(const VarName: string; Data: Pointer);
      TEnumVarsCallback = reference to procedure(const EnvVar: TPJEnvironmentVar; Data: Pointer);
    // ...
    class procedure EnumNames(Callback: TEnumNamesCallback; Data: Pointer);
    class procedure EnumVars(Callback: TEnumVarsCallback; Data: Pointer);
  end;

The old TPJEnvVarsEnum and TPJEnvVarsEnumEx types could either be removed or be deprecated and redefined as follows (after TPJEnvironmentVars):

type
  TPJEnvVarsEnum = TPJEnvironmentVars.TEnumNamesCallback deprecated;
  TPJEnvVarsEnumEx = TPJEnvironmentVars.TEnumVarsCallback deprecated;

Remove or deprecate TPJEnvVarsEnumerator

Although TPJEnvVarsEnumerator can be used stand alone, its real purpose is to provide an enumerator for the component. If the component is removed (issue #1) then there is no real need to keep this enumerator class.

Given that TPJEnvironmentVars provides various enumerator methods there is no real need to use TPJEnvVarsEnumerator as a stand alone enumerator, especially since the TPJEnvironmentVars methods are easier to use.

Therefore TPJEnvVarsEnumerator could be deleted, given that it is not currently deprecated, it could be retained but deprecated.

Add `ToString` & `Size` functions to TPJEnvironmentVar

A common thing to do us to render an environment variable in name=value format. Add a ToString method to do this.

It is useful (eg when creating environment blocks) to know the size in chars of an environment variable in name=value format. So add a Size method to return the size in characters. (The size in bytes will be SizeOf(Char) * Size).

Add comparison operators to TPJEnvironmentVar

It could be useful to be able to compare TPJEnvironmentVar records.

Need to decide how to compare. Do we consider two records to be equal if their names are the same or if both name and value are the same.

Tests need to be case insensitive because Windows considers environment variable names to be the same if they differ only in the case of the letters.

Rename units into DelphiDabbler.Lib namespace

Rename units as:

  • DelphiDabbler.Lib.EnvVars
  • DelphiDabbler.Lib.EnvVarsDsgn

.dcr file will need renaming similarly.

The will be a breaking change so needs introducing at the next major version release.

Replace array types with `TArray<T>` specialisations

TStringDynArray can be replaced with TArray<string> or array of string as appropriate.

Similarly TPJEnvironmentVarArray can be replaced by TArray<TPJEnvironmentVar> or array of TPJEnvironmentVar.

The definition of the TPJEnvironmentVarArray type can either be deleted or deprecated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.