1599099600

# How to Use If-Else Statements and Loops in R – Dataquest

When we’re programming in R (or any other language, for that matter), we often want to control when and how particular parts of our code are executed. We can do that using control structures like if-else statements, for loops, and while loops.

Control structures are blocks of code that determine how other sections of code are executed based on specified parameters. You can think of these as a bit like the instructions a parent might give a child before leaving the house:

“If I’m not home by 8pm, make yourself dinner.”

Control structures set a condition and tell R what to do when that condition is met or not met. And unlike some kids, R will always do what we tell it to! You can learn more about control structures in the R documentation if you would like.

In this tutorial, we assume you’re familiar with basic data structures, and arithmetic operations in R.

Not quite there yet? Check out our Introductory R Programming course that’s part of our Data Analyst in R path. It’s free to start learning, there are no prerequisites, and there’s nothing to install — you can start learning in your browser right now.

install.packages(“Dataquest”)

Start learning R today with our Introduction to R course — no credit card required!

(This tutorial is based on our intermediate R programming course, so check that out as well! It’s interactive and will allow you to write and run code right in your browser.)

### Comparison Operators in R

In order to use control structures, we need to create statements that will turn out to be either TRUE or FALSE. In the kids example above, the statement “It’s 8pm. Are my parents home yet?” yields TRUE (“Yes”) or FALSE (“No”). In R, the most fundamental way to evaluate something as TRUE or FALSE is through comparison operators.

Below are six essential comparison operators for working with control structures in R:

• == means equality. The statement x == a framed as a question means “Does the value of x equal the value of a?”
• != means “not equal”. The statement x == b means “Does the value of x not equal the value of b?”
• < means “less than”. The statement x < c means “Is the value of x less than the value of c?”
• <= means “less than or equal”. The statement x <= d means “Is the value of x less or equal to the value of d?”
• > means “greater than”. The statement x > e means “Is the value of x greater than the value of e?”
• >= means “greater than or equal”. The statement x >= f means “Is the value of xgreater than or equal to the value of f?”

#data science tutorials #beginner #for loop #for loops #if #if else #learn r #r #r tutorial #rstats #tutorial #tutorials #while loop #while loops

1599099600

## How to Use If-Else Statements and Loops in R – Dataquest

When we’re programming in R (or any other language, for that matter), we often want to control when and how particular parts of our code are executed. We can do that using control structures like if-else statements, for loops, and while loops.

Control structures are blocks of code that determine how other sections of code are executed based on specified parameters. You can think of these as a bit like the instructions a parent might give a child before leaving the house:

“If I’m not home by 8pm, make yourself dinner.”

Control structures set a condition and tell R what to do when that condition is met or not met. And unlike some kids, R will always do what we tell it to! You can learn more about control structures in the R documentation if you would like.

In this tutorial, we assume you’re familiar with basic data structures, and arithmetic operations in R.

Not quite there yet? Check out our Introductory R Programming course that’s part of our Data Analyst in R path. It’s free to start learning, there are no prerequisites, and there’s nothing to install — you can start learning in your browser right now.

install.packages(“Dataquest”)

Start learning R today with our Introduction to R course — no credit card required!

(This tutorial is based on our intermediate R programming course, so check that out as well! It’s interactive and will allow you to write and run code right in your browser.)

### Comparison Operators in R

In order to use control structures, we need to create statements that will turn out to be either TRUE or FALSE. In the kids example above, the statement “It’s 8pm. Are my parents home yet?” yields TRUE (“Yes”) or FALSE (“No”). In R, the most fundamental way to evaluate something as TRUE or FALSE is through comparison operators.

Below are six essential comparison operators for working with control structures in R:

• == means equality. The statement x == a framed as a question means “Does the value of x equal the value of a?”
• != means “not equal”. The statement x == b means “Does the value of x not equal the value of b?”
• < means “less than”. The statement x < c means “Is the value of x less than the value of c?”
• <= means “less than or equal”. The statement x <= d means “Is the value of x less or equal to the value of d?”
• > means “greater than”. The statement x > e means “Is the value of x greater than the value of e?”
• >= means “greater than or equal”. The statement x >= f means “Is the value of xgreater than or equal to the value of f?”

#data science tutorials #beginner #for loop #for loops #if #if else #learn r #r #r tutorial #rstats #tutorial #tutorials #while loop #while loops

1667425440

## pdf2gerb

Perl script converts PDF files to Gerber format

Pdf2Gerb generates Gerber 274X photoplotting and Excellon drill files from PDFs of a PCB. Up to three PDFs are used: the top copper layer, the bottom copper layer (for 2-sided PCBs), and an optional silk screen layer. The PDFs can be created directly from any PDF drawing software, or a PDF print driver can be used to capture the Print output if the drawing software does not directly support output to PDF.

The general workflow is as follows:

2. Print the top and bottom copper and top silk screen layers to a PDF file.
3. Run Pdf2Gerb on the PDFs to create Gerber and Excellon files.
4. Use a Gerber viewer to double-check the output against the original PCB design.
6. Submit the files to a PCB manufacturer.

Please note that Pdf2Gerb does NOT perform DRC (Design Rule Checks), as these will vary according to individual PCB manufacturer conventions and capabilities. Also note that Pdf2Gerb is not perfect, so the output files must always be checked before submitting them. As of version 1.6, Pdf2Gerb supports most PCB elements, such as round and square pads, round holes, traces, SMD pads, ground planes, no-fill areas, and panelization. However, because it interprets the graphical output of a Print function, there are limitations in what it can recognize (or there may be bugs).

See docs/Pdf2Gerb.pdf for install/setup, config, usage, and other info.

## pdf2gerb_cfg.pm

#Pdf2Gerb config settings:
#Put this file in same folder/directory as pdf2gerb.pl itself (global settings),
#or copy to another folder/directory with PDFs if you want PCB-specific settings.
#There is only one user of this file, so we don't need a custom package or namespace.
#NOTE: all constants defined in here will be added to main namespace.
#package pdf2gerb_cfg;

use strict; #trap undef vars (easier debug)
use warnings; #other useful info (easier debug)

##############################################################################################
#configurable settings:
#change values here instead of in main pfg2gerb.pl file

use constant WANT_COLORS => (\$^O !~ m/Win/); #ANSI colors no worky on Windows? this must be set < first DebugPrint() call

#just a little warning; set realistic expectations:
#DebugPrint("\${\(CYAN)}Pdf2Gerb.pl \${\(VERSION)}, \$^O O/S\n\${\(YELLOW)}\${\(BOLD)}\${\(ITALIC)}This is EXPERIMENTAL software.  \nGerber files MAY CONTAIN ERRORS.  Please CHECK them before fabrication!\${\(RESET)}", 0); #if WANT_DEBUG

use constant METRIC => FALSE; #set to TRUE for metric units (only affect final numbers in output files, not internal arithmetic)
use constant APERTURE_LIMIT => 0; #34; #max #apertures to use; generate warnings if too many apertures are used (0 to not check)
use constant DRILL_FMT => '2.4'; #'2.3'; #'2.4' is the default for PCB fab; change to '2.3' for CNC

use constant WANT_DEBUG => 0; #10; #level of debug wanted; higher == more, lower == less, 0 == none
use constant GERBER_DEBUG => 0; #level of debug to include in Gerber file; DON'T USE FOR FABRICATION
use constant WANT_STREAMS => FALSE; #TRUE; #save decompressed streams to files (for debug)
use constant WANT_ALLINPUT => FALSE; #TRUE; #save entire input stream (for debug ONLY)

#DebugPrint(sprintf("\${\(CYAN)}DEBUG: stdout %d, gerber %d, want streams? %d, all input? %d, O/S: \$^O, Perl: \$]\${\(RESET)}\n", WANT_DEBUG, GERBER_DEBUG, WANT_STREAMS, WANT_ALLINPUT), 1);
#DebugPrint(sprintf("max int = %d, min int = %d\n", MAXINT, MININT), 1);

#define standard trace and pad sizes to reduce scaling or PDF rendering errors:
#This avoids weird aperture settings and replaces them with more standardized values.
#(I'm not sure how photoplotters handle strange sizes).
#Fewer choices here gives more accurate mapping in the final Gerber files.
#units are in inches
use constant TOOL_SIZES => #add more as desired
(
#round or square pads (> 0) and drills (< 0):
.010, -.001,  #tiny pads for SMD; dummy drill size (too small for practical use, but needed so StandardTool will use this entry)
.031, -.014,  #used for vias
.041, -.020,  #smallest non-filled plated hole
.051, -.025,
.056, -.029,  #useful for IC pins
.070, -.033,
#    .090, -.043,  #NOTE: 600 dpi is not high enough resolution to reliably distinguish between .043" and .046", so choose 1 of the 2 here
.100, -.046,
.115, -.052,
.130, -.061,
.140, -.067,
.150, -.079,
.175, -.088,
.190, -.093,
.200, -.100,
.220, -.110,
.160, -.125,  #useful for mounting holes
#some additional pad sizes without holes (repeat a previous hole size if you just want the pad size):
.090, -.040,  #want a .090 pad option, but use dummy hole size
.065, -.040, #.065 x .065 rect pad
.035, -.040, #.035 x .065 rect pad
#traces:
.001,  #too thin for real traces; use only for board outlines
.006,  #minimum real trace width; mainly used for text
.008,  #mainly used for mid-sized text, not traces
.010,  #minimum recommended trace width for low-current signals
.012,
.015,  #moderate low-voltage current
.020,  #heavier trace for power, ground (even if a lighter one is adequate)
.025,
.030,  #heavy-current traces; be careful with these ones!
.040,
.050,
.060,
.080,
.100,
.120,
);
#Areas larger than the values below will be filled with parallel lines:
#This cuts down on the number of aperture sizes used.
#Set to 0 to always use an aperture or drill, regardless of size.
use constant { MAX_APERTURE => max((TOOL_SIZES)) + .004, MAX_DRILL => -min((TOOL_SIZES)) + .004 }; #max aperture and drill sizes (plus a little tolerance)
#DebugPrint(sprintf("using %d standard tool sizes: %s, max aper %.3f, max drill %.3f\n", scalar((TOOL_SIZES)), join(", ", (TOOL_SIZES)), MAX_APERTURE, MAX_DRILL), 1);

#NOTE: Compare the PDF to the original CAD file to check the accuracy of the PDF rendering and parsing!
#for example, the CAD software I used generated the following circles for holes:
#CAD hole size:   parsed PDF diameter:      error:
#  .014                .016                +.002
#  .020                .02267              +.00267
#  .025                .026                +.001
#  .029                .03167              +.00267
#  .033                .036                +.003
#  .040                .04267              +.00267
#This was usually ~ .002" - .003" too big compared to the hole as displayed in the CAD software.
#To compensate for PDF rendering errors (either during CAD Print function or PDF parsing logic), adjust the values below as needed.
#units are pixels; for example, a value of 2.4 at 600 dpi = .0004 inch, 2 at 600 dpi = .0033"
use constant
{
HOLE_ADJUST => -0.004 * 600, #-2.6, #holes seemed to be slightly oversized (by .002" - .004"), so shrink them a little
RNDPAD_ADJUST => -0.003 * 600, #-2, #-2.4, #round pads seemed to be slightly oversized, so shrink them a little
SQRPAD_ADJUST => +0.001 * 600, #+.5, #square pads are sometimes too small by .00067, so bump them up a little
TRACE_ADJUST => 0, #(pixels) traces seemed to be okay?
REDUCE_TOLERANCE => .001, #(inches) allow this much variation when reducing circles and rects
};

#Also, my CAD's Print function or the PDF print driver I used was a little off for circles, so define some additional adjustment values here:
#Values are added to X/Y coordinates; units are pixels; for example, a value of 1 at 600 dpi would be ~= .002 inch
use constant
{
CIRCLE_ADJUST_MINY => -0.001 * 600, #-1, #circles were a little too high, so nudge them a little lower
CIRCLE_ADJUST_MAXX => +0.001 * 600, #+1, #circles were a little too far to the left, so nudge them a little to the right
SUBST_CIRCLE_CLIPRECT => FALSE, #generate circle and substitute for clip rects (to compensate for the way some CAD software draws circles)
WANT_CLIPRECT => TRUE, #FALSE, #AI doesn't need clip rect at all? should be on normally?
RECT_COMPLETION => FALSE, #TRUE, #fill in 4th side of rect when 3 sides found
};

use constant SOLDER_MARGIN => +.012; #units are inches

#line join/cap styles:
use constant
{
CAP_NONE => 0, #butt (none); line is exact length
CAP_ROUND => 1, #round cap/join; line overhangs by a semi-circle at either end
CAP_SQUARE => 2, #square cap/join; line overhangs by a half square on either end
CAP_OVERRIDE => FALSE, #cap style overrides drawing logic
};

#number of elements in each shape type:
use constant
{
RECT_SHAPELEN => 6, #x0, y0, x1, y1, count, "rect" (start, end corners)
LINE_SHAPELEN => 6, #x0, y0, x1, y1, count, "line" (line seg)
CURVE_SHAPELEN => 10, #xstart, ystart, x0, y0, x1, y1, xend, yend, count, "curve" (bezier 2 points)
CIRCLE_SHAPELEN => 5, #x, y, 5, count, "circle" (center + radius)
};
#const my %SHAPELEN =
our %SHAPELEN =
(
rect => RECT_SHAPELEN,
line => LINE_SHAPELEN,
curve => CURVE_SHAPELEN,
circle => CIRCLE_SHAPELEN,
);

#panelization:
#This will repeat the entire body the number of times indicated along the X or Y axes (files grow accordingly).
#Display elements that overhang PCB boundary can be squashed or left as-is (typically text or other silk screen markings).
#Set "overhangs" TRUE to allow overhangs, FALSE to truncate them.
use constant PANELIZE => {'x' => 1, 'y' => 1, 'xpad' => 0, 'ypad' => 0, 'overhangs' => TRUE}; #number of times to repeat in X and Y directions

# Set this to 1 if you need TurboCAD support.
#\$turboCAD = FALSE; #is this still needed as an option?

#CIRCAD pad generation uses an appropriate aperture, then moves it (stroke) "a little" - we use this to find pads and distinguish them from PCB holes.
use constant PAD_STROKE => 0.3; #0.0005 * 600; #units are pixels
#convert very short traces to pads or holes:
use constant TRACE_MINLEN => .001; #units are inches
#use constant ALWAYS_XY => TRUE; #FALSE; #force XY even if X or Y doesn't change; NOTE: needs to be TRUE for all pads to show in FlatCAM and ViewPlot
use constant REMOVE_POLARITY => FALSE; #TRUE; #set to remove subtractive (negative) polarity; NOTE: must be FALSE for ground planes

#PDF uses "points", each point = 1/72 inch
#combined with a PDF scale factor of .12, this gives 600 dpi resolution (1/72 * .12 = 600 dpi)
use constant INCHES_PER_POINT => 1/72; #0.0138888889; #multiply point-size by this to get inches

# The precision used when computing a bezier curve. Higher numbers are more precise but slower (and generate larger files).
#\$bezierPrecision = 100;
use constant BEZIER_PRECISION => 36; #100; #use const; reduced for faster rendering (mainly used for silk screen and thermal pads)

# Ground planes and silk screen or larger copper rectangles or circles are filled line-by-line using this resolution.
use constant FILL_WIDTH => .01; #fill at most 0.01 inch at a time

# The max number of characters to read into memory
use constant MAX_BYTES => 10 * M; #bumped up to 10 MB, use const

use constant DUP_DRILL1 => TRUE; #FALSE; #kludge: ViewPlot doesn't load drill files that are too small so duplicate first tool

my \$runtime = time(); #Time::HiRes::gettimeofday(); #measure my execution time

print STDERR "Loaded config settings from '\${\(__FILE__)}'.\n";
1; #last value must be truthful to indicate successful load

#############################################################################################
#junk/experiment:

#use Package::Constants;
#use Exporter qw(import); #https://perldoc.perl.org/Exporter.html

#my \$caller = "pdf2gerb::";

#sub cfg
#{
#    my \$proto = shift;
#    my \$class = ref(\$proto) || \$proto;
#    my \$settings =
#    {
#        \$WANT_DEBUG => 990, #10; #level of debug wanted; higher == more, lower == less, 0 == none
#    };
#    bless(\$settings, \$class);
#    return \$settings;
#}

#use constant HELLO => "hi there2"; #"main::HELLO" => "hi there";
#use constant GOODBYE => 14; #"main::GOODBYE" => 12;

#our @EXPORT_OK = Package::Constants->list(__PACKAGE__); #https://www.perlmonks.org/?node_id=1072691; NOTE: "_OK" skips short/common names

#print STDERR scalar(@EXPORT_OK) . " consts exported:\n";
#foreach(@EXPORT_OK) { print STDERR "\$_\n"; }
#my \$val = main::thing("xyz");
#print STDERR "caller gave me \$val\n";
#foreach my \$arg (@ARGV) { print STDERR "arg \$arg\n"; }

Author: swannman
Source Code: https://github.com/swannman/pdf2gerb

1649209980

## C# REPL

A cross-platform command line REPL for the rapid experimentation and exploration of C#. It supports intellisense, installing NuGet packages, and referencing local .NET projects and assemblies.

(click to view animation)

C# REPL provides the following features:

• Syntax highlighting via ANSI escape sequences
• Intellisense with fly-out documentation
• Nuget package installation
• Reference local assemblies, solutions, and projects
• Navigate to source via Source Link
• IL disassembly (both Debug and Release mode)
• Fast and flicker-free rendering. A "diff" algorithm is used to only render what's changed.

## Installation

C# REPL is a .NET 6 global tool, and runs on Windows 10, Mac OS, and Linux. It can be installed via:

dotnet tool install -g csharprepl

If you're running on Mac OS Catalina (10.15) or later, make sure you follow any additional directions printed to the screen. You may need to update your PATH variable in order to use .NET global tools.

After installation is complete, run csharprepl to begin. C# REPL can be updated via dotnet tool update -g csharprepl.

## Usage:

Run csharprepl from the command line to begin an interactive session. The default colorscheme uses the color palette defined by your terminal, but these colors can be changed using a theme.json file provided as a command line argument.

### Evaluating Code

Type some C# into the prompt and press Enter to run it. The result, if any, will be printed:

> Console.WriteLine("Hello World")
Hello World

[6/7/2021 5:13:00 PM]

To evaluate multiple lines of code, use Shift+Enter to insert a newline:

> var x = 5;
var y = 8;
x * y
40

Additionally, if the statement is not a "complete statement" a newline will automatically be inserted when Enter is pressed. For example, in the below code, the first line is not a syntactically complete statement, so when we press enter we'll go down to a new line:

> if (x == 5)
| // caret position, after we press Enter on Line 1

Finally, pressing Ctrl+Enter will show a "detailed view" of the result. For example, for the DateTime.Now expression below, on the first line we pressed Enter, and on the second line we pressed Ctrl+Enter to view more detailed output:

> DateTime.Now // Pressing Enter shows a reasonable representation
[5/30/2021 5:13:00 PM]

> DateTime.Now // Pressing Ctrl+Enter shows a detailed representation
[5/30/2021 5:13:00 PM] {
Date: [5/30/2021 12:00:00 AM],
Day: 30,
DayOfWeek: Sunday,
DayOfYear: 150,
Hour: 17,
InternalKind: 9223372036854775808,
InternalTicks: 637579915804530992,
Kind: Local,
Millisecond: 453,
Minute: 13,
Month: 5,
Second: 0,
Ticks: 637579915804530992,
TimeOfDay: [17:13:00.4530992],
Year: 2021,
_dateData: 9860951952659306800
}

A note on semicolons: C# expressions do not require semicolons, but statements do. If a statement is missing a required semicolon, a newline will be added instead of trying to run the syntatically incomplete statement; simply type the semicolon to complete the statement.

> var now = DateTime.Now; // assignment statement, semicolon required

> DateTime.Now.AddDays(8) // expression, we don't need a semicolon
[6/7/2021 5:03:05 PM]

### Keyboard Shortcuts

• Basic Usage
• Ctrl+C - Cancel current line
• Ctrl+L - Clear screen
• Enter - Evaluate the current line if it's a syntactically complete statement; otherwise add a newline
• Control+Enter - Evaluate the current line, and return a more detailed representation of the result
• Shift+Enter - Insert a new line (this does not currently work on Linux or Mac OS; Hopefully this will work in .NET 7)
• Ctrl+Shift+C - Copy current line to clipboard
• Ctrl+V, Shift+Insert, and Ctrl+Shift+V - Paste text to prompt. Automatically trims leading indent
• Code Actions
• F1 - Opens the MSDN documentation for the class/method under the caret (example)
• F9 - Shows the IL (intermediate language) for the current statement in Debug mode.
• Ctrl+F9 - Shows the IL for the current statement with Release mode optimizations.
• F12 - Opens the source code in the browser for the class/method under the caret, if the assembly supports Source Link.
• Autocompletion
• Ctrl+Space - Open autocomplete menu. If there's a single option, pressing Ctrl+Space again will select the option
• Enter, Right Arrow, Tab - Select active autocompletion option
• Escape - closes autocomplete menu
• Home and End - Navigate to beginning of a single line and end of a single line, respectively
• Ctrl+Home and Ctrl+End - Navigate to beginning of line and end across multiple lines in a multiline prompt, respectively
• Arrows - Navigate characters within text
• Ctrl+Arrows - Navigate words within text
• Ctrl+Backspace - Delete previous word
• Ctrl+Delete - Delete next word

Use the #r command to add assembly or nuget references.

• For assembly references, run #r "AssemblyName" or #r "path/to/assembly.dll"
• For project references, run #r "path/to/project.csproj". Solution files (.sln) can also be referenced.
• For nuget references, run #r "nuget: PackageName" to install the latest version of a package, or #r "nuget: PackageName, 13.0.5" to install a specific version (13.0.5 in this case).

To run ASP.NET applications inside the REPL, start the csharprepl application with the --framework parameter, specifying the Microsoft.AspNetCore.App shared framework. Then, use the above #r command to reference the application DLL. See the Command Line Configuration section below for more details.

csharprepl --framework  Microsoft.AspNetCore.App

## Command Line Configuration

The C# REPL supports multiple configuration flags to control startup, behavior, and appearance:

csharprepl [OPTIONS] [response-file.rsp] [script-file.csx] [-- <additional-arguments>]

Supported options are:

• OPTIONS:
• -r <dll> or --reference <dll>: Reference an assembly, project file, or nuget package. Can be specified multiple times. Uses the same syntax as #r statements inside the REPL. For example, csharprepl -r "nuget:Newtonsoft.Json" "path/to/myproj.csproj"
• When an assembly or project is referenced, assemblies in the containing directory will be added to the assembly search path. This means that you don't need to manually add references to all of your assembly's dependencies (e.g. other references and nuget packages). Referencing the main entry assembly is enough.
• -u <namespace> or --using <namespace>: Add a using statement. Can be specified multiple times.
• -f <framework> or --framework <framework>: Reference a shared framework. The available shared frameworks depends on the local .NET installation, and can be useful when running an ASP.NET application from the REPL. Example frameworks are:
• Microsoft.NETCore.App (default)
• Microsoft.AspNetCore.All
• Microsoft.AspNetCore.App
• Microsoft.WindowsDesktop.App
• -t <theme.json> or --theme <theme.json>: Read a theme file for syntax highlighting. This theme file associates C# syntax classifications with colors. The color values can be full RGB, or ANSI color names (defined in your terminal's theme). The NO_COLOR standard is supported.
• --trace: Produce a trace file in the current directory that logs CSharpRepl internals. Useful for CSharpRepl bug reports.
• -v or --version: Show version number and exit.
• -h or --help: Show help and exit.
• response-file.rsp: A filepath of an .rsp file, containing any of the above command line options.
• script-file.csx: A filepath of a .csx file, containing lines of C# to evaluate before starting the REPL. Arguments to this script can be passed as <additional-arguments>, after a double hyphen (--), and will be available in a global args variable.

If you have dotnet-suggest enabled, all options can be tab-completed, including values provided to --framework and .NET namespaces provided to --using.

## Integrating with other software

C# REPL is a standalone software application, but it can be useful to integrate it with other developer tools:

### Windows Terminal

To add C# REPL as a menu entry in Windows Terminal, add the following profile to Windows Terminal's settings.json configuration file (under the JSON property profiles.list):

{
"name": "C# REPL",
"commandline": "csharprepl"
},

To get the exact colors shown in the screenshots in this README, install the Windows Terminal Dracula theme.

### Visual Studio Code

To use the C# REPL with Visual Studio Code, simply run the csharprepl command in the Visual Studio Code terminal. To send commands to the REPL, use the built-in Terminal: Run Selected Text In Active Terminal command from the Command Palette (workbench.action.terminal.runSelectedText).

### Windows OS

To add the C# REPL to the Windows Start Menu for quick access, you can run the following PowerShell command, which will start C# REPL in Windows Terminal:

\$shell = New-Object -ComObject WScript.Shell
\$shortcut.TargetPath = "wt.exe"
\$shortcut.Arguments = "-w 0 nt csharprepl.exe"
\$shortcut.Save()

You may also wish to add a shorter alias for C# REPL, which can be done by creating a .cmd file somewhere on your path. For example, put the following contents in C:\Users\username\.dotnet\tools\csr.cmd:

wt -w 0 nt csharprepl

This will allow you to launch C# REPL by running csr from anywhere that accepts Windows commands, like the Window Run dialog.

## Comparison with other REPLs

This project is far from being the first REPL for C#. Here are some other projects; if this project doesn't suit you, another one might!

Visual Studio's C# Interactive pane is full-featured (it has syntax highlighting and intellisense) and is part of Visual Studio. This deep integration with Visual Studio is both a benefit from a workflow perspective, and a drawback as it's not cross-platform. As far as I know, the C# Interactive pane does not support NuGet packages or navigating to documentation/source code. Subjectively, it does not follow typical command line keybindings, so can feel a bit foreign.

csi.exe ships with C# and is a command line REPL. It's great because it's a cross platform REPL that comes out of the box, but it doesn't support syntax highlighting or autocompletion.

dotnet script allows you to run C# scripts from the command line. It has a REPL built-in, but the predominant focus seems to be as a script runner. It's a great tool, though, and has a strong community following.

dotnet interactive is a tool from Microsoft that creates a Jupyter notebook for C#, runnable through Visual Studio Code. It also provides a general framework useful for running REPLs.

Author: waf
Source Code: https://github.com/waf/CSharpRepl

1567822183

## How to Build Virtual Assistant with Python

In this lab we are going to build demo TARS from Interstellar movie with Python. TARS can help you to automate your tasks such as search videos in YouTube and play them, send emails, open websites, search materials in Wikipedia and read them,inform weather forecast in your country, greetings and more. By building TARS you will increase your Python knowledge and learn many useful libraries/tools. I will push source code to my git repository so feel free to contribute and improve functionality of TARS

Let’s start by creating virtual environment and building the base audio system of TARS.

mkdir TARS
cd TARS
virtualenv venv

To activate the venv run command below

. venv/bin/activate

What is virtual environment?

Once you activated venv, we need to install main libraries by following commands:

pip3 install gTTS
pip3 install SpeechRecognition
pip3 install PyAudio
pip3 install pygame

gTTS (Google Text-to-Speech) is a Python library and CLI tool to interface with Google Translate’s text-to-speech API. This module helps to convert String text to Spoken text and can be saved as .mp3

Speech Recognition is an important feature in several applications used such as home automation, artificial intelligence, etc. Recognizing speech needs audio input, and SpeechRecognition makes it really simple to retrieve this input. Instead of building scripts from scratch to access microphones and process audio files, SpeechRecognition will have you up and running in just a few minutes.

To access your microphone with SpeechRecognizer, you’ll have to install the PyAudio package

Pygame is a cross-platform set of Python modules designed for writing video games. It includes computer graphics and sound libraries designed to be used with the Python programming language.

Now, let’s build voice system of TARS:

from gtts import gTTS
import speech_recognition as sr
from pygame import mixer

def talk(audio):
print(audio)
for line in audio.splitlines():
text_to_speech = gTTS(text=audio, lang='en-uk')
text_to_speech.save('audio.mp3')
mixer.init()
mixer.music.play()

As you see we are passing audio as an argument to let the TARS speak. For instance, talk(‘Hey I am TARS! How can I help you?’) program will loop these lines with the help of splitlines() method. This method is used to split the lines at line boundaries. Check splitlines() for more. Then, gTTS will handle to convert all these texts to speech. text parameter defines text to be read and lang defines the language (IETF language tag) to read the text in. Once loop finished, save() method writes result to file.

pygame.mixer is a module for loading and playing sounds and must be initialized before using it.

Alright! Now, let’s create a function that will listen for commands.

def myCommand():
#Initialize the recognizer
r = sr.Recognizer()

with sr.Microphone() as source:
r.pause_threshold = 1
#wait for a second to let the recognizer adjust the
#energy threshold based on the surrounding noise level
#listens for the user's input
audio = r.listen(source)

try:
print('You said: ' + command + '\n')

#loop back to continue to listen for commands if unrecognizable speech is received
except sr.UnknownValueError:
print('Your last command couldn\'t be heard')
command = myCommand();

return command

In this function we are using SpeechRecognition library. It acts as a wrapper for several popular speech APIs and is thus extremely flexible. One of these—the Google Web Speech API—supports a default API key that is hard-coded into the SpeechRecognition library. That means you can get off your feet without having to sign up for a service.

To be able to work with your own voice with speech recognition, you need the PyAudio package. Like Recognizer for audio files, we will need Microphone for real-time speech data.

You can capture input from the microphone using the listen() method of the Recognizer class inside of the with block. This method takes an audio source as its first argument and records input from the source until silence is detected.

Try to say your commands in silence place( with less background noise ) otherwise TARS can confuse.

import random

def tars(command):
errors=[
"I don\'t know what you mean!",
"Excuse me?",
]

if 'Hello' in command:

else:
error = random.choice(errors)
talk(error)

while True:
assistant(myCommand())

Once you run the program TARS will start talk with you by saying ‘TARS is ready!’ and continue to listen your commands until you stop the program. Start by saying ‘Hello’ :)

When TARS didn’t get the command we will handle the error by random sentences.

Here is the full code of main structure:

from gtts import gTTS
import speech_recognition as sr
from pygame import mixer
import random
def talk(audio):
print(audio)
for line in audio.splitlines():
text_to_speech = gTTS(text=audio, lang='en-uk')
text_to_speech.save('audio.mp3')
mixer.init()
mixer.music.play()

def myCommand():
#Initialize the recognizer
#The primary purpose of a Recognizer instance is, of course, to recognize speech.
r = sr.Recognizer()

with sr.Microphone() as source:
r.pause_threshold = 2
#wait for a second to let the recognizer adjust the
#energy threshold based on the surrounding noise level
#listens for the user's input
audio = r.listen(source)

try:
print('You said: ' + command + '\n')

#loop back to continue to listen for commands if unrecognizable speech is received
except sr.UnknownValueError:
print('Your last command couldn\'t be heard')
command = myCommand();
return command

def tars(command):
errors=[
"I don't know what you mean",
"Did you mean astronaut?",
]
if 'hello' in command:
else:
error = random.choice(errors)
talk(error)

#loop to continue executing multiple commands
while True:
tars(myCommand())

Well… Is AI anything more than a bunch of IF statements?

If you are talking about “real” AI , then yes it’s a lot more than just If statements.The development of AI has historically been split into two fields; symbolic AI, and machine learning.

Symbolic AI is the field in which artificially intelligent systems were designed with if-else type logic. Programmers would attempt to define every possible scenario for the system to deal with. Until the late seventies this was the dominant form of AI system development. Experts in the field argued very strongly that machine-learning would never catch on and that AI could only be written in this way.

Now we know that accounting for every possible scenario in an intelligent system is enormously impractical and we use machine-learning instead. Machine learning uses statistics to look for and define patterns in data so that a machine can learn about and improve the tasks that it is designed to perform. This is significantly more flexible.

We are using just bunch of IF statements to understand basics of AI. But we will implement some cool ML algorithms later.

I hope you learned new things so far, now, it is time to teach TARS how to automate stuff.

Open Google and search for something

We are going to import webbrowser module in Python which provides an interface to display Web-based documents.

While we are saying commands, TARS have to detect availability of these commands by matching them. Python has a built-in package called re, which can be used to work with Regular Expressions.

import re
import webbrowser

#matching command to check it is available
reg_ex = re.search('open google (.*)', command)
if reg_ex:
url = url + 'r/' + subreddit
webbrowser.open(url)
print('Done!')

The re.search() method takes a regular expression pattern and a string and searches for that pattern within the string. If the search is successful, search() returns a match object or None otherwise. Therefore, the search is usually immediately followed by an if-statement to test if the search succeeded

The code reg_ex = re.search('open google (.)', command)* stores the search result in a variable named “reg_ex”. Then the if-statement tests the match – if true the search succeeded and group() is the matching text. Otherwise if the match is false (None to be more specific), then the search did not succeed, and there is no matching text. The 1 in reg_ex.group(1) represents the first parenthesized subgroup.

Even you can install Selenium to make search in Google by TARS. To install Selenium run the following command:

pip3 install selenium

Selenium WebDriver is a collection of open source APIs which are used to automate the testing of a web application. This tool is used to automate web application testing to verify that it works as expected. It supports many browsers such as Safari, Firefox, IE, and Chrome.

You can search how to use Selenium with Python there is a lot of sources on internet and it is really easy to learn. Let’s add this feature to TARS

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

if 'open google and search' in command:
reg_ex = re.search('open google and search (.*)', command)
search_for = command.split("search",1)[1]
if reg_ex:
url = url + 'r/' + subgoogle
talk('Okay!')
driver = webdriver.Firefox(executable_path='/path/to/geckodriver') #depends which web browser you are using
search = driver.find_element_by_name('q') # finds search
search.send_keys(str(search_for)) #sends search keys
search.send_keys(Keys.RETURN) #hits enter

TARS will consider strings after “open google and search” command and takes all words as a search keys. I am using Firefox so I installed geckodriver but if you are using Chrome check the following StackOverflow question.

#### Send Email

We are going to import smtplib to send emails with Python. SMTP stands for Simple Mail Transfer Protocol and it is useful for communicating with mail servers to send mail.

import smtplib

elif 'email' or 'gmail' in command:
talk('What is the subject?')
time.sleep(3)
subject = myCommand()
talk('What should I say?')
time.sleep(3)
message = myCommand()
content = 'Subject: {}\n\n{}'.format(subject, message)

#init gmail SMTP
mail = smtplib.SMTP('smtp.gmail.com', 587)

#identify to server
mail.ehlo()

#encrypt session
mail.starttls()

#send message
mail.sendmail('FROM', 'TO', content)

#end mail connection
mail.close()

talk('Email sent.')

Note that, in a nutshell, google is not allowing you to log in via smtplib because it has flagged this sort of login as “less secure”, so what you have to do is go to this link while you’re logged in to your google account, and allow the access.

Crawl Data

We are doing great so far! TARS can send mails and search whatever you want on google. Now, let’s implement more complex function to make TARS crawl some Wikipedia data and read it for us.

Beautiful Soup is a Python library for pulling data out of HTML and XML files. It works with your favorite parser to provide idiomatic ways of navigating, searching, and modifying the parse tree. It commonly saves programmers hours or days of work. Run the following command in your terminal to install beautifulsoup:

pip install beautifulsoup4

We also will need requests library for making HTTP requests in Python. It abstracts the complexities of making requests behind a beautiful, simple API so that you can focus on interacting with services and consuming data in your application. Alright! Let’s see the code:

import bs4
import requests

elif 'wikipedia' in command:
reg_ex = re.search('search in wikipedia (.+)', command)
if reg_ex:
query = command.split()
response = requests.get("https://en.wikipedia.org/wiki/" + query[3])

if response is not None:
html = bs4.BeautifulSoup(response.text, 'html.parser')
paragraphs = html.select("p")
for para in paragraphs:
print (para.text)

intro = '\n'.join([ para.text for para in paragraphs[0:5]])
print (intro)
mp3name = 'speech.mp3'
language = 'en'
myobj = gTTS(text=intro, lang=language, slow=False)
myobj.save(mp3name)
mixer.init()
mixer.music.play()
elif 'stop' in command:
mixer.music.stop()

“search in wikipedia Mars” and TARS will take “Mars” as a keyword to search in Wikipedia. If you search something on Wikipedia you will see URL will look like https://en.wikipedia.org/wiki/Keyword so we are sending get request with keyword(what to search) to access data. Once request succeed, beautifulsoup will parse content inside Wikipedia. The join() method is a string method and returns a string in which the elements of sequence have been joined by str separator and we are using it to separate paragraphs. You already familiar with gTTS and mixer so I am passing that part.

TARS will display the crawled data on console and start to reading it for you.

Search videos on YouTube and play

This function is similar to search with google but this time it is better to use urllib. The main objective is to learn new things with Python, so I don’t want include Selenium in this function. Here is the code:

import urllib.request #used to make requests
import urllib.parse #used to parse values into the url

talk('Ok!')
if reg_ex:
query_string = urllib.parse.urlencode({"search_query" : domain})
pass

The urllib module in Python 3 allows you access websites via your program. This opens up as many doors for your programs as the internet opens up for you. urllib in Python 3 is slightly different than urllib2 in Python 2, but they are mostly the same. Through urllib, you can access websites, download data, parse data, modify your headers, and do any GET and POST requests you might need to do.

Check this tutorial for more about urllib

Search key must be encoded before parsing into url. If you search something on YouTube you can see after [http://www.youtube.com/results?"](http://www.youtube.com/results?"http://www.youtube.com/results?"”) there is a encoded search keys. Once these search keys encoded program can successfully access search results. The expression re.findall() returns all the non-overlapping matches of patterns in a string as a list of strings. Each video on youtube has its own 11 characters ID (https://www.youtube.com/watch?v=gEPmA3USJdI)and re.findall() will find all matches in decoded html_content(in search results page). decode() is used to convert from one encoding scheme, in which argument string is encoded to the desired encoding scheme. This works opposite to the encode. It accepts the encoding of the encoding string to decode it and returns the original string. Finally, it plays first video in search results because usually the first video is nearest one for search keys.

Full Code:

from gtts import gTTS
import speech_recognition as sr
import re
import time
import webbrowser
import random
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import smtplib
import requests
from pygame import mixer
import urllib.request
import urllib.parse
import bs4

def talk(audio):
"speaks audio passed as argument"

print(audio)
for line in audio.splitlines():
text_to_speech = gTTS(text=audio, lang='en-uk')
text_to_speech.save('audio.mp3')
mixer.init()
mixer.music.play()

def myCommand():
"listens for commands"
#Initialize the recognizer
#The primary purpose of a Recognizer instance is, of course, to recognize speech.
r = sr.Recognizer()

with sr.Microphone() as source:
r.pause_threshold = 1
#wait for a second to let the recognizer adjust the
#energy threshold based on the surrounding noise level
#listens for the user's input
audio = r.listen(source)
print('analyzing...')

try:
print('You said: ' + command + '\n')
time.sleep(2)

#loop back to continue to listen for commands if unrecognizable speech is received
except sr.UnknownValueError:
print('Your last command couldn\'t be heard')
command = myCommand();

return command

def tars(command):
errors=[
"I don't know what you mean",
"Excuse me?",
]
"if statements for executing commands"

if 'open google and search' in command:
reg_ex = re.search('open google and search (.*)', command)
search_for = command.split("search",1)[1]
print(search_for)
if reg_ex:
url = url + 'r/' + subgoogle
talk('Okay!')
driver = webdriver.Firefox(executable_path='/home/coderasha/Desktop/geckodriver')
search = driver.find_element_by_name('q')
search.send_keys(str(search_for))
search.send_keys(Keys.RETURN) # hit return after you enter search text

#Send Email
elif 'email' in command:
talk('What is the subject?')
time.sleep(3)
subject = myCommand()
talk('What should I say?')
message = myCommand()
content = 'Subject: {}\n\n{}'.format(subject, message)

#init gmail SMTP
mail = smtplib.SMTP('smtp.gmail.com', 587)

#identify to server
mail.ehlo()

#encrypt session
mail.starttls()

#send message
mail.sendmail('FROM', 'TO', content)

#end mail connection
mail.close()

talk('Email sent.')

# search in wikipedia (e.g. Can you search in wikipedia apples)
elif 'wikipedia' in command:
reg_ex = re.search('wikipedia (.+)', command)
if reg_ex:
query = command.split("wikipedia",1)[1]
response = requests.get("https://en.wikipedia.org/wiki/" + query)
if response is not None:
html = bs4.BeautifulSoup(response.text, 'html.parser')
paragraphs = html.select("p")
for para in paragraphs:
print (para.text)
intro = '\n'.join([ para.text for para in paragraphs[0:3]])
print (intro)
mp3name = 'speech.mp3'
language = 'en'
myobj = gTTS(text=intro, lang=language, slow=False)
myobj.save(mp3name)
mixer.init()
while mixer.music.play()
elif 'stop' in command:
mixer.music.stop()

# Search videos on Youtube and play (e.g. Search in youtube believer)
talk('Ok!')
if reg_ex:
query_string = urllib.parse.urlencode({"search_query" : domain})
pass

elif 'hello' in command:
time.sleep(3)
elif 'who are you' in command:
talk('I am one of four former U.S. Marine Corps tactical robots')
time.sleep(3)
else:
error = random.choice(errors)
talk(error)
time.sleep(3)

talk('TARS activated!')

#loop to continue executing multiple commands
while True:
time.sleep(4)
tars(myCommand())

Cool! We just created demo TARS and I hope you learned many things from this lab. Please feel free to contribute this project on GitHub, TARS will wait for improvements.

I hope this tutorial will surely help and you if you liked this tutorial, please consider sharing it with others.

#python #web-development

1661092140

## ud.hpp

#pragma once
#include <optional>
#include <string>
#include <vector>
#include <array>
#include <algorithm>
#include <string_view>
#include <fstream>
#include <unordered_map>

#include <Windows.h>
#include <winternl.h>

#if defined(_MSC_VER)
#define UD_FORCEINLINE __forceinline
#pragma warning( push )
#pragma warning( disable : 4244 4083 )
#else
#define UD_FORCEINLINE __attribute__( ( always_inline ) )
#endif

#define ud_encode_c( str ) ud::rot::decode( ud::rot::rot_t<str>{ } ).data
#define ud_encode( str ) std::string_view( ud::rot::decode( ud::rot::rot_t<str>{ } ) )

#define ud_xorstr_c( str ) ud::xorstr::decrypt( ud::xorstr::xorstr_t< str, __COUNTER__ + 1 ^ 0x90 >{ } ).data
#define ud_xorstr( str ) std::string_view{ ud::xorstr::decrypt( ud::xorstr::xorstr_t< str, __COUNTER__ + 1 ^ 0x90 >{ } ) }

#define ud_stack_str( str ) ud::details::comp_string_t{ str }.data

#define ud_import( mod, func )	reinterpret_cast< decltype( &func ) >( ud::lazy_import::find_module_export< TEXT( mod ), #func >( ) )
#define ud_first_import( func ) reinterpret_cast< decltype( &func ) >( ud::lazy_import::find_first_export< #func >( ) )

// preprocessed settings due to MSVC (not clang or gcc) throwing errors even in `if constexpr` bodies
#define UD_USE_SEH false

namespace ud
{
namespace details
{
struct LDR_DATA_TABLE_ENTRY32
{

std::uintptr_t dll_base;
std::uintptr_t entry_point;
std::size_t size_of_image;

UNICODE_STRING full_name;
UNICODE_STRING base_name;
};

struct LDR_DATA_TABLE_ENTRY64
{
LIST_ENTRY dummy_0;
LIST_ENTRY dummy_1;

std::uintptr_t dll_base;
std::uintptr_t entry_point;
union {
unsigned long size_of_image;
const char* _dummy;
};

UNICODE_STRING full_name;
UNICODE_STRING base_name;
};

#if defined( _M_X64 )
using LDR_DATA_TABLE_ENTRY = LDR_DATA_TABLE_ENTRY64;
#else
using LDR_DATA_TABLE_ENTRY = LDR_DATA_TABLE_ENTRY32;
#endif

template < std::size_t sz >
struct comp_string_t
{
std::size_t size = sz;
char data[ sz ]{ };

comp_string_t( ) = default;
consteval explicit comp_string_t( const char( &str )[ sz ] )
{
std::copy_n( str, sz, data );
}

constexpr explicit operator std::string_view( ) const
{
return { data, size };
}
};

template < std::size_t sz >
struct wcomp_string_t
{
std::size_t size = sz;
wchar_t data[ sz ]{ };

wcomp_string_t( ) = default;
consteval explicit wcomp_string_t( const wchar_t( &str )[ sz ] )
{
std::copy_n( str, sz, data );
}

constexpr explicit operator std::wstring_view( ) const
{
return { data, size };
}
};

inline constexpr std::uint64_t multiplier = 0x5bd1e995;
inline consteval std::uint64_t get_seed( )
{
constexpr auto time_str = __TIME__;
constexpr auto time_len = sizeof( __TIME__ ) - 1;

constexpr auto time_int = [ ] ( const char* const str, const std::size_t len )
{
auto res = 0ull;
for ( auto i = 0u; i < len; ++i )
if ( str[ i ] >= '0' && str[ i ] <= '9' )
res = res * 10 + str[ i ] - '0';

return res;
}( time_str, time_len );

return time_int;
}

template < auto v >
struct constant_t
{
enum : decltype( v )
{
value = v
};
};

template < auto v >
inline constexpr auto constant_v = constant_t< v >::value;

#undef max
#undef min

template < std::uint32_t seq >
consteval std::uint64_t recursive_random( )
{
constexpr auto seed = get_seed( );
constexpr auto mask = std::numeric_limits< std::uint64_t >::max( );

constexpr auto x = ( ( seq * multiplier ) + seed ) & mask;
constexpr auto x_prime = ( x >> 0x10 ) | ( x << 0x10 );

return constant_v< x_prime >;
}
}

namespace rot
{
template < details::comp_string_t str >
struct rot_t
{
char rotted[ str.size ];

[[nodiscard]] consteval const char* encoded( ) const
{
return rotted;
}

consteval rot_t( )
{
for ( auto i = 0u; i < str.size; ++i )
{
const auto c = str.data[ i ];
const auto set = c >= 'A' && c <= 'Z' ? 'A' : c >= 'a' && c <= 'z' ? 'a' : c;

if ( set == 'a' || set == 'A' )
rotted[ i ] = ( c - set - 13 + 26 ) % 26 + set;

else
rotted[ i ] = c;
}
}
};

template < details::comp_string_t str >
UD_FORCEINLINE details::comp_string_t< str.size > decode( rot_t< str > encoded )
{
details::comp_string_t< str.size > result{ };

for ( auto i = 0u; i < str.size; ++i )
{
const auto c = encoded.rotted[ i ];
const auto set = c >= 'A' && c <= 'Z' ? 'A' : c >= 'a' && c <= 'z' ? 'a' : c;

if ( set == 'a' || set == 'A' )
result.data[ i ] = ( c - set - 13 + 26 ) % 26 + set;

else
result.data[ i ] = c;
}

return result;
}
}

namespace fnv
{
inline constexpr std::uint32_t fnv_1a( const char* const str, const std::size_t size )
{
constexpr auto prime = 16777619u;

std::uint32_t hash = 2166136261;

for ( auto i = 0u; i < size; ++i )
{
hash ^= str[ i ];
hash *= prime;
}

return hash;
}

inline constexpr std::uint32_t fnv_1a( const wchar_t* const str, const std::size_t size )
{
constexpr auto prime = 16777619u;

std::uint32_t hash = 2166136261;

for ( auto i = 0u; i < size; ++i )
{
hash ^= static_cast< char >( str[ i ] );
hash *= prime;
}

return hash;
}

inline constexpr std::uint32_t fnv_1a( const std::wstring_view str )
{
return fnv_1a( str.data( ), str.size( ) );
}

inline constexpr std::uint32_t fnv_1a( const std::string_view str )
{
return fnv_1a( str.data( ), str.size( ) );
}

template < details::comp_string_t str >
consteval std::uint32_t fnv_1a( )
{
return fnv_1a( str.data, str.size );
}

template < details::wcomp_string_t str >
consteval std::uint32_t fnv_1a( )
{
return fnv_1a( str.data, str.size );
}
}

namespace xorstr
{
template < details::comp_string_t str, std::uint32_t key_multiplier >
struct xorstr_t
{
char xored[ str.size ];

[[nodiscard]] consteval std::uint64_t xor_key( ) const
{
return details::recursive_random< key_multiplier >( );
}

consteval xorstr_t( )
{
for ( auto i = 0u; i < str.size; ++i )
xored[ i ] = str.data[ i ] ^ xor_key( );
}
};

template < details::comp_string_t str, std::uint32_t key_multiplier >
UD_FORCEINLINE details::comp_string_t< str.size > decrypt( xorstr_t< str, key_multiplier > enc )
{
details::comp_string_t< str.size > result{ };

for ( auto i = 0u; i < str.size; ++i )
{
const auto c = enc.xored[ i ];

result.data[ i ] = c ^ enc.xor_key( );
}

return result;
}
}

namespace lazy_import
{
UD_FORCEINLINE std::uintptr_t get_module_handle( const std::uint64_t hash )
{
#if defined( _M_X64 )
const auto peb = reinterpret_cast< const PEB* >( __readgsqword( 0x60 ) );
#else
const auto peb = reinterpret_cast< const PEB* >( __readfsdword( 0x30 ) );
#endif

const auto modules = reinterpret_cast< const LIST_ENTRY* >( peb->Ldr->InMemoryOrderModuleList.Flink );

for ( auto i = modules->Flink; i != modules; i = i->Flink )
{
const auto entry = reinterpret_cast< const details::LDR_DATA_TABLE_ENTRY* >( i );

const auto name = entry->base_name.Buffer;
const auto len = entry->base_name.Length;

if ( fnv::fnv_1a( static_cast< const wchar_t* >( name ), len ) == hash )
return entry->dll_base;
}

return 0;
}

UD_FORCEINLINE void* find_primitive_export( const std::uint64_t dll_hash, const std::uint64_t function_hash )
{
const auto module = get_module_handle( dll_hash );

if ( !module )
return nullptr;

const auto dos = reinterpret_cast< const IMAGE_DOS_HEADER* >( module );
const auto nt = reinterpret_cast< const IMAGE_NT_HEADERS* >( module + dos->e_lfanew );

const auto names = reinterpret_cast< const std::uint32_t* >( module + exports->AddressOfNames );
const auto ordinals = reinterpret_cast< const std::uint16_t* >( module + exports->AddressOfNameOrdinals );
const auto functions = reinterpret_cast< const std::uint32_t* >( module + exports->AddressOfFunctions );

for ( auto i = 0u; i < exports->NumberOfNames; ++i )
{
const auto name = reinterpret_cast< const char* >( module + names[ i ] );
std::size_t len = 0;

for ( ; name[ len ]; ++len );

if ( fnv::fnv_1a( name, len ) == function_hash )
return reinterpret_cast< void* >( module + functions[ ordinals[ i ] ] );
}

return nullptr;
}

template < details::wcomp_string_t dll_name, details::comp_string_t function_name >
UD_FORCEINLINE void* find_module_export( )
{
return find_primitive_export( fnv::fnv_1a< dll_name >( ), fnv::fnv_1a< function_name >( ) );
}

template < details::comp_string_t function_name >
UD_FORCEINLINE void* find_first_export( )
{
constexpr auto function_hash = fnv::fnv_1a< function_name >( );

#if defined( _M_X64 )
const auto peb = reinterpret_cast< const PEB* >( __readgsqword( 0x60 ) );
#else
const auto peb = reinterpret_cast< const PEB* >( __readfsdword( 0x30 ) );
#endif

const auto modules = reinterpret_cast< const LIST_ENTRY* >( peb->Ldr->InMemoryOrderModuleList.Flink );

for ( auto i = modules->Flink; i != modules; i = i->Flink )
{
const auto entry = reinterpret_cast< const details::LDR_DATA_TABLE_ENTRY* >( i );

const auto name = entry->base_name.Buffer;
std::size_t len = 0;

if ( !name )
continue;

for ( ; name[ len ]; ++len );

if ( const auto exp = find_primitive_export( fnv::fnv_1a( name, len ), function_hash ) )
return exp;
}

return nullptr;
}
}

template < typename ty = std::uintptr_t >
std::optional< ty > find_pattern_primitive( const std::uintptr_t start, const std::uintptr_t end, const std::string_view pattern )
{
std::vector< std::pair< bool, std::uint8_t > > bytes;

for ( auto it = pattern.begin( ); it != pattern.end( ); ++it )
{
if ( *it == ' ' )
continue;

else if ( *it == '?' )
{
if ( it + 1 < pattern.end( ) && *( it + 1 ) == '?' )
{
bytes.push_back( { true, 0x00 } );
++it;
}

else
bytes.push_back( { false, 0x00 } );
}

else
{
if ( it + 1 == pattern.end( ) )
break;

const auto get_byte = [ ] ( const std::string& x ) -> std::uint8_t
{
return static_cast< std::uint8_t >( std::stoul( x, nullptr, 16 ) );
};

bytes.emplace_back( false, get_byte( std::string( it - 1, ( ++it ) + 1 ) ) );
}
}

for ( auto i = reinterpret_cast< const std::uint8_t* >( start ); i < reinterpret_cast< const std::uint8_t* >( end ); )
{
auto found = true;
for ( const auto& [ is_wildcard, byte ] : bytes )
{
++i;

if ( is_wildcard )
continue;

if ( *i != byte )
{
found = false;
break;
}
}

if ( found )
return ty( i - bytes.size( ) + 1 );
}

return std::nullopt;
}

struct segment_t
{
std::string_view name = "";
std::uintptr_t start{ }, end{ };
std::size_t size{ };

template < typename ty = std::uintptr_t >
std::optional< ty > find_pattern( const std::string_view pattern ) const
{
return find_pattern_primitive< ty >( start, end, pattern );
}

explicit segment_t( const std::string_view segment_name )
{
init( GetModuleHandle( nullptr ), segment_name );
}

segment_t( const void* const module, const std::string_view segment_name )
{
init( module, segment_name );
}

segment_t( const void* const handle, const IMAGE_SECTION_HEADER* section )
{
init( handle, section );
}

private:
void init( const void* const handle, const IMAGE_SECTION_HEADER* section )
{
name = std::string_view( reinterpret_cast< const char* >( section->Name ), 8 );
start = reinterpret_cast< std::uintptr_t >( handle ) + section->VirtualAddress;
end = start + section->Misc.VirtualSize;
size = section->Misc.VirtualSize;
}

void init( const void* const handle, const std::string_view segment_name )
{
const auto dos = reinterpret_cast< const IMAGE_DOS_HEADER* >( handle );
const auto nt = reinterpret_cast< const IMAGE_NT_HEADERS* >( reinterpret_cast< const std::uint8_t* >( handle ) + dos->e_lfanew );

for ( auto i = 0u; i < nt->FileHeader.NumberOfSections; ++i )
{
if ( std::string_view( reinterpret_cast< const char* >( section[ i ].Name ), 8 ).find( segment_name ) != std::string_view::npos )
{
start = reinterpret_cast< std::uintptr_t >( handle ) + section[ i ].VirtualAddress;
end = start + section[ i ].Misc.VirtualSize;
size = section[ i ].Misc.VirtualSize;
name = segment_name;
return;
}
}
}
};

#pragma code_seg( push, ".text" )
template < auto... bytes>
struct shellcode_t
{
static constexpr std::size_t size = sizeof...( bytes );
__declspec( allocate( ".text" ) ) static constexpr std::uint8_t data[ ]{ bytes... };
};
#pragma code_seg( pop )

template < typename ty, auto... bytes >
constexpr ty make_shellcode( )
{
return reinterpret_cast< const ty >( &shellcode_t< bytes... >::data );
}

template < std::uint8_t... bytes >
UD_FORCEINLINE constexpr void emit( )
{
#if defined( __clang__ ) || defined( __GNUC__ )
constexpr std::uint8_t data[ ]{ bytes... };

for ( auto i = 0u; i < sizeof...( bytes ); ++i )
__asm volatile( ".byte %c0\t\n" :: "i" ( data[ i ] ) );
#endif
}

template < std::size_t size, std::uint32_t seed = __COUNTER__ + 0x69, std::size_t count = 0 >
UD_FORCEINLINE constexpr void emit_random( )
{
if constexpr ( count < size )
{
constexpr auto random = details::recursive_random< seed >( );
emit< static_cast< std::uint8_t >( random ) >( );
emit_random< size, static_cast< std::uint32_t >( random )* seed, count + 1 >( );
}
}

inline bool is_valid_page( const void* const data, const std::uint32_t flags = PAGE_READWRITE )
{
MEMORY_BASIC_INFORMATION mbi{ };

if ( !VirtualQuery( data, &mbi, sizeof( mbi ) ) )
return false;

return mbi.Protect & flags;
}

struct export_t
{
std::string_view name;
std::uint16_t ordinal{ };
};

struct module_t
{
std::string name;
std::uintptr_t start, end;

segment_t operator[ ]( const std::string_view segment_name ) const
{
return { reinterpret_cast< const void* >( start ), segment_name };
}

std::vector< export_t > get_exports( ) const
{
const auto dos = reinterpret_cast< const IMAGE_DOS_HEADER* >( start );
const auto nt = reinterpret_cast< const IMAGE_NT_HEADERS* >( start + dos->e_lfanew );

return { };

const auto export_dir = reinterpret_cast< const IMAGE_EXPORT_DIRECTORY* >( start + directory_header.VirtualAddress );
const auto name_table = reinterpret_cast< const std::uint32_t* >( start + export_dir->AddressOfNames );
const auto ord_table = reinterpret_cast< const std::uint16_t* >( start + export_dir->AddressOfNameOrdinals );
const auto addr_table = reinterpret_cast< const std::uint32_t* >( start + export_dir->AddressOfFunctions );

std::vector< export_t > exports( export_dir->NumberOfNames );

for ( auto i = 0u; i < export_dir->NumberOfNames; ++i )
{
const auto name_str = reinterpret_cast< const char* >( start + name_table[ i ] );
const auto ord = ord_table[ i ];

exports[ i ] = { name_str, ord, addr };
}

return exports;
}

[[nodiscard]] std::vector< segment_t > get_segments( ) const
{
const auto dos = reinterpret_cast< const IMAGE_DOS_HEADER* >( start );
const auto nt = reinterpret_cast< const IMAGE_NT_HEADERS* >( start + dos->e_lfanew );

std::vector< segment_t > segments;

for ( auto i = 0u; i < nt->FileHeader.NumberOfSections; ++i )
{
const segment_t seg( dos, &section[ i ] );
segments.push_back( seg );
}

return segments;
}

[[nodiscard]] std::vector< export_t > get_imports( ) const
{
const auto dos = reinterpret_cast< const IMAGE_DOS_HEADER* >( start );
const auto nt = reinterpret_cast< const IMAGE_NT_HEADERS* >( start + dos->e_lfanew );

return { };

const auto import_dir = reinterpret_cast< const IMAGE_IMPORT_DESCRIPTOR* >( start + directory_header->VirtualAddress );
std::vector< export_t > imports;

for ( auto i = 0u;; ++i )
{
if ( !import_dir[ i ].OriginalFirstThunk )
break;

const auto directory = &import_dir[ i ];

const auto name_table = reinterpret_cast< const std::uint32_t* >( start + directory->OriginalFirstThunk );
const auto addr_table = reinterpret_cast< const std::uint32_t* >( start + directory->FirstThunk );

for ( auto j = 0u;; ++j )
{
if ( !addr_table[ j ] )
break;

if ( !name_table[ j ] )
continue;

std::string_view name_str;

constexpr auto name_alignment = 2;

const auto name_ptr = reinterpret_cast< const char* >( start + name_table[ j ] ) + name_alignment;

#if UD_USE_SEH
// using SEH here is not a very good solution
// however, it's faster than querying that page protection to see if it's readable
__try
{
name = name_ptr;
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
name = "";
}
#else
// runtime overhead of ~3us compared to SEH on single calls
// on bulk calls it can go up to ~300-500us
name_str = is_valid_page( name_ptr, PAGE_READONLY ) ? name_ptr : "";
#endif

// emplace_back doesn't allow for implicit conversion, so we have to do it manually
imports.push_back( { name_str, static_cast< std::uint16_t >( j ), reinterpret_cast< std::uintptr_t >( addr ) } );
}
}

return imports;
}

template < typename ty = std::uintptr_t >
ty get_address( const std::string_view name ) const
{
for ( const auto& export_ : get_exports( ) )
{
if ( export_.name.find( name ) != std::string_view::npos )
}

return 0;
}

template < typename ty = std::uintptr_t >
std::optional< ty > find_pattern( const std::string_view pattern ) const
{
return find_pattern_primitive< ty >( start, end, pattern );
}

[[nodiscard]] std::vector< std::string_view > get_strings( const std::size_t minimum_size = 0 ) const
{
std::vector< std::string_view > result;

const auto rdata = ( *this )[ ".rdata" ];

if ( !rdata.size )
return { };

const auto start = reinterpret_cast< const std::uint8_t* >( rdata.start );
const auto end = reinterpret_cast< const std::uint8_t* >( rdata.end );

for ( auto i = start; i < end; ++i )
{
if ( *i == 0 || *i > 127 )
continue;

const auto str = reinterpret_cast< const char* >( i );
const auto sz = std::strlen( str );

if ( !sz || sz < minimum_size )
continue;

result.emplace_back( str, sz );
i += sz;
}

return result;
}

module_t( )
{
init( GetModuleHandle( nullptr ) );
}

explicit module_t( void* const handle )
{
init( handle );
}

explicit module_t( const std::string_view module_name )
{
init( GetModuleHandleA( module_name.data( ) ) );
}

private:
void* module;

void init( void* const handle )
{
module = handle;

const auto dos = reinterpret_cast< const IMAGE_DOS_HEADER* >( handle );
const auto nt = reinterpret_cast< const IMAGE_NT_HEADERS* >( reinterpret_cast< const std::uint8_t* >( handle ) + dos->e_lfanew );

start = reinterpret_cast< std::uintptr_t >( handle );

char buffer[ MAX_PATH ];
const auto sz = GetModuleFileNameA( static_cast< HMODULE >( handle ), buffer, MAX_PATH );

name = sz ? std::string{ buffer, sz } : std::string{ };
}
};

inline std::vector< module_t > get_modules( )
{
std::vector< module_t > result;

#if defined( _M_X64 )
const auto peb = reinterpret_cast< const PEB* >( __readgsqword( 0x60 ) );
#else
const auto peb = reinterpret_cast< const PEB* >( __readfsdword( 0x30 ) );
#endif

const auto modules = reinterpret_cast< const LIST_ENTRY* >( peb->Ldr->InMemoryOrderModuleList.Flink );
for ( auto i = modules->Flink; i != modules; i = i->Flink )
{
const auto entry = reinterpret_cast< const LDR_DATA_TABLE_ENTRY* >( i );

if ( entry->Reserved2[ 0 ] || entry->DllBase )
result.emplace_back( entry->Reserved2[ 0 ] ? entry->Reserved2[ 0 ] : entry->DllBase );
}

return result;
}

{
for ( const auto& module : get_modules( ) )
{
return module;
}

return std::nullopt;
}

inline std::optional< export_t > get_export( const std::uintptr_t address )
{
for ( const auto& module : get_modules( ) )
{
{
const auto exports = module.get_exports( );
for ( const auto& export_ : exports )
{
return export_;
}
}
}

return std::nullopt;
}

template < typename rel_t, typename ty = std::uintptr_t >
ty calculate_relative( const std::uintptr_t address, const std::uint8_t size, const std::uint8_t offset )
{
return ty( address + *reinterpret_cast< rel_t* >( address + offset ) + size );
}
}

template < std::size_t size >
UD_FORCEINLINE std::ostream& operator<<( std::ostream& os, const ud::details::comp_string_t< size >& str )
{
return os << std::string_view{ str.data, str.size };
}

#if defined( _MSC_VER )
#pragma warning( pop )
#endif

Author: AmJayden
Source code: https://github.com/AmJayden/udlib

#cpluplus