strLen boosted

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
aGerman
Expert
Posts: 4716
Joined: 22 Jan 2010 18:01
Location: Germany

Re: strLen boosted

#31 Post by aGerman » 06 Jul 2025 14:54

It's really unreadable, and the variable names are, at best, ugly.
Agreed. At least I tried to have it consistently ugly :lol:
However, it's tricky to get reliable time measurements on a modern system, where the CPU frequency fluctuates constantly.
Yeah. To mitigate it I run the tests in realtime priority. This makes sure we get always fed with enough resources. Without it I get results that are occasionally double as high as usual.

FWIW, that's how your code performs on my notebook if I add it to my test code.

Code: Select all

~~~~~~~~~~~~~~~~~~~~
jeb

8191
00:00:01.44
8191
00:00:01.49
8191
00:00:01.49
8191
00:00:01.49

1000
00:00:01.25
1000
00:00:01.28
1000
00:00:01.27
1000
00:00:01.27

200
00:00:01.11
200
00:00:01.15
200
00:00:01.14
200
00:00:01.16

10
00:00:01.11
10
00:00:01.16
10
00:00:01.14
10
00:00:01.14
Drücken Sie eine beliebige Taste . . .
Excluding the code for long strings makes processing short strings as quick as expected.

Code: Select all

%$lib.macrodefine.free% set strLen=for %%# in (1 2) do if %%#==2 ( %$\n%
    for /f "tokens=1,2" %%1 in ("%%!args%%!") do ( %$\n%
        set L=0 %$\n%
        if defined %%~1 ( %$\n%
            if "" neq "%%!%%~1:~255%%!" ( %$\n%
                for %%# in (4095 2047 1023 511 255) do ( %$\n%
                    set /a t=L+%%# %$\n%
                    for %%T in (%%!t%%!) do ( %$\n%
                        if "" neq "%%!%%~1:~%%T%%!" set /a L=%%T+1 %$\n%
                    ) %$\n%
                ) %$\n%
            ) %$\n%
            for %%# in (%%!L%%!) do ( %$\n%
                set ^"$=%%!%%~1:~%%#%%!^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCC^
BBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAA99999999999999998888888888888888^
7777777777777777666666666666666655555555555555554444444444444444^
333333333333333322222222222222221111111111111111^" %$\n%
                set /a L+=0x%%!$:~511,1%%!%%!$:~255,1%%! %$\n%
            ) %$\n%
        ) %$\n%
        for %%# in (%%!L%%!) do ( %$\n%
            endlocal %$\n%
            set %%~2=%%# %$\n%
        ) %$\n%
    ) %$\n%
 ) else setlocal EnableDelayedExpansion ^& set args=

Code: Select all

~~~~~~~~~~~~~~~~~~~~
jeb

8191
00:00:01.51
8191
00:00:01.55
8191
00:00:01.54
8191
00:00:01.53

1000
00:00:01.27
1000
00:00:01.30
1000
00:00:01.30
1000
00:00:01.30

200
00:00:00.69
200
00:00:00.72
200
00:00:00.70
200
00:00:00.71

10
00:00:00.69
10
00:00:00.71
10
00:00:00.72
10
00:00:00.71
Drücken Sie eine beliebige Taste . . .
Steffen

aGerman
Expert
Posts: 4716
Joined: 22 Jan 2010 18:01
Location: Germany

Re: strLen boosted

#32 Post by aGerman » 09 Jul 2025 13:40

I don't feel like continuing to try to squeeze out every last hundredth of a second 🤯
That's it for now:

Code: Select all

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:initStrLen
:: Computes the number of bytes in a string.
:: %strLen% str len
::   str - [ByRef In] Name of the variable containing the string to be measured.
::   len - [ByRef Out] Name of the variable that receives the measured length.
:: Strings of up to 8191 characters are supported.
                                                FOR /F %%! IN ("! ^! ^^^!") DO ^
set strLen=for %%. in (1 2) do if %%.==2 (^
  for /f "tokens=1,2" %%1 in ("%%!args%%!") do (^
    set "L=0"^&^
    (if defined %%~1^
      (if "" neq "%%!%%~1:~255%%!"^
        (if "" neq "%%!%%~1:~4095%%!"^
          (set "S=%%!%%~1:~4096%%!"^&set "L=4096") else set "S=%%!%%~1%%!"^
        )^&^
        (if defined S^
          set ^"scale=^
%%!S:~255,1%%!%%!S:~511,1%%!%%!S:~767,1%%!%%!S:~1023,1%%!%%!S:~1279,1%%!^
%%!S:~1535,1%%!%%!S:~1791,1%%!%%!S:~2047,1%%!%%!S:~2303,1%%!%%!S:~2559,1%%!^
%%!S:~2815,1%%!%%!S:~3071,1%%!%%!S:~3327,1%%!%%!S:~3583,1%%!%%!S:~3839,1%%!^
FEDCBA9876543210^"^&^
          set /a "L+=0x%%!scale:~15,1%%!*256"^
        )^
      )^&^
      for %%# in (%%!L%%!) do set ^"S=%%!%%~1:~%%#%%!^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCC^
BBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAA99999999999999998888888888888888^
7777777777777777666666666666666655555555555555554444444444444444^
333333333333333322222222222222221111111111111111^"^&^
      set /a "L+=0x%%!S:~511,1%%!%%!S:~255,1%%!"^
    )^&^
    for %%# in (%%!L%%!) do endlocal^&set "%%~2=%%#"^
  )^
) else setlocal EnableDelayedExpansion^&set args=

goto :eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I hope it's also a little more readable now, even if I refrained from defining any additional variables for just a single macro. Indentations are still broken as we can't indent string continuations. Although it's harder to understand, the %%! is beneficial. That's why I used it now instead of the escaped exclamation marks.


Test code:

Code: Select all

:: make sure we are in the spotlight:
@if "%~1"=="" start /realtime conhost "%~f0" 1&exit /b
@echo off &setlocal DisableDelayedExpansion

:: 8191
set str1=^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
:: 1000
set "str2=%str1:~,1000%"
:: 200
set "str3=%str1:~,200%"
:: 10
set "str4=%str1:~,10%"

call :initTimediff

:: uncomment this to get the evidence that it also works with delayed expansion enabled
::setlocal EnableDelayedExpansion

echo(
echo ~~~~~~~~~~~~~~~~~~~~
echo Steffen
call :initStrLenSteffen
call :test str1
call :test str2
call :test str3
call :test str4

echo(
echo ~~~~~~~~~~~~~~~~~~~~
echo Francesco
call :initStrLenFrancesco
call :test str1
call :test str2
call :test str3
call :test str4

echo(
echo ~~~~~~~~~~~~~~~~~~~~
echo jeb
call :initStrLenJeb
call :test str1
call :test str2
call :test str3
call :test str4

echo(
echo ~~~~~~~~~~~~~~~~~~~~
echo final combination
call :initStrLen
call :test str1
call :test str2
call :test str3
call :test str4

pause
exit /b

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:initStrLenSteffen
setlocal DisableDelayedExpansion

:: Computes the number of bytes in a string.
:: %strLen% str len
::   str - [ByRef In] Name of the variable containing the string to be measured.
::   len - [ByRef Out] Name of the variable that receives the measured length.
:: Strings of up to 8191 characters are supported.
set strLen=for %%- in (1 2) do if %%-==2 (^
setlocal EnableDelayedExpansion^&for /f "tokens=1,2" %%. in ("^^!`^^!") do ^
set #=0^&(if defined %%~. (if ` neq ^^!%%~.:~4095^^!` ^
(set $=^^!%%~.:~4096^^!F^&set /a #+=4096) else set $=^^!%%~.^^!F)^&^
(for %%# in (2048 1024 512 256) do if ` neq ^^!$:~%%#^^!` ^
set $=^^!$:~%%#^^!^&set /a #+=%%#)^&set $=^^!$^^!^
EDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCC^
BBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAA99999999999999998888888888888888^
7777777777777777666666666666666655555555555555554444444444444444^
333333333333333322222222222222221111111111111111^&^
set /a #+=0x^^!$:~511,1^^!^^!$:~255,1^^!)^&^
for %%# in (^^!#^^!) do endlocal^&set %%~/=%%#) else set `=

endlocal&set "strLen=%strLen%"
if !!# neq # set "strLen=%strLen:^^=%"
goto :eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:initStrLenFrancesco
setlocal DisableDelayedExpansion

set strLen=for %%- in (1 2) do if %%-==2 (^
setlocal EnableDelayedExpansion^&for /f "tokens=1,2" %%. in ("^^!`^^!") do ^
set #=0^&(if defined %%~. (if ` neq ^^!%%~.:~4095^^!` ^
(set $=^^!%%~.:~4096^^!^&set #=4096) else set $=^^!%%~.^^!)^&^
(if defined $ if "^^!$:~255,1^^!" neq "" ^
set "t=^^!$:~3839,1^^!^^!$:~3583,1^^!^^!$:~3327,1^^!^^!$:~3071,1^^!^^!$:~2815,1^^!^^!$:~2559,1^^!^^!$:~2303,1^^!^^!$:~2047,1^^!^^!$:~1791,1^^!^^!$:~1535,1^^!^^!$:~1279,1^^!^^!$:~1023,1^^!^^!$:~767,1^^!^^!$:~511,1^^!^^!$:~255,1^^!FEDCBA9876543210"^&^
set /a "#+=t=0x^^!t:~15,1^^!*256"^&for %%# in (^^!t^^!) do set "$=^^!$:~%%#^^!")^&^
if defined $ ^
set "t=^^!$:~239,1^^!^^!$:~223,1^^!^^!$:~207,1^^!^^!$:~191,1^^!^^!$:~175,1^^!^^!$:~159,1^^!^^!$:~143,1^^!^^!$:~127,1^^!^^!$:~111,1^^!^^^!$:~95,1^^!^^!$:~79,1^^!^^!$:~63,1^^!^^!$:~47,1^^!^^!$:~31,1^^!^^!$:~15,1^^!FEDCBA9876543210"^&^
set /a "t=0x^^!t:~15,1^^!*16"^&for %%# in (^^!t^^!) do ^
set "$=^^!$:~%%#^^!FEDCBA9876543210"^&set /a "#+=t+0x^^!$:~15,1^^!")^&^
for %%# in (^^!#^^!) do endlocal^&set %%~/=%%#) else set `=

endlocal&set "strLen=%strLen%"
if !!# neq # set "strLen=%strLen:^^=%"
goto :eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:initStrLenJeb
::: Macro to define macros without knowing the delayed expansion mode
::: Usage:
::: %$lib.macrodefine.free% set my_macro=...
:::
::: Reserved FOR variables:
::: %%! - contains one !
::: %%^ - results into one caret, attention read the other comments!
:::
::: While defining a new macro:
::: - Each bang ! has to be changed to %%!   regex-replace: (?<!%%)! -> %%!

::: - Each caret ^ has to be changed to %%^^ regex-replace: (?<!%%)\^ -> %%^^
::: - If carets are inside quotes replace them only with %%^  .
::: - But be careful only replace carets that should be placed in the macro itself
::: - Carets can also be used for escaping special chars in the definition phase, like ^&, ^<, ^|, ^"
FOR /F "tokens=1 delims== " %%! in ("!=! ^^^!") DO ^
FOR /F %%^^ in ("^ ^^^^%%!=%%!") DO ^
set ^"$lib.macrodefine.free=@FOR /F "tokens=1 delims== " %%%%! in ("%%!=%%! %%^%%^%%^%%!") DO ^
@FOR /F %%%%^^%%^^ in ("%%^ %%^%%^%%^%%^%%^%%!=%%^%%!") DO @"

REM *** Defining a line feed for usage while defining macros
(set ^"$\n=^^^
%=empty=%
)
@REM %$lib.macrodefine.free% echo "Test1: %%! and %%^ --"
@REM %$lib.macrodefine.free% echo  Test2: %%! and %%^^ --

:: Computes the number of bytes in a string.
:: %strLen% str len
::   str - [ByRef In] Name of the variable containing the string to be measured.
::   len - [ByRef Out] Name of the variable that receives the measured length.
:: Strings of up to 8191 characters are supported.
%$lib.macrodefine.free% set strLen=for %%# in (1 2) do if %%#==2 ( %$\n%
    for /f "tokens=1,2" %%1 in ("%%!args%%!") do ( %$\n%
        set L=0 %$\n%
        if defined %%~1 ( %$\n%
            if "" neq "%%!%%~1:~255%%!" ( %$\n%
                for %%# in (4095 2047 1023 511 255) do ( %$\n%
                    set /a t=L+%%# %$\n%
                    for %%T in (%%!t%%!) do ( %$\n%
                        if "" neq "%%!%%~1:~%%T%%!" set /a L=%%T+1 %$\n%
                    ) %$\n%
                ) %$\n%
            ) %$\n%
            for %%# in (%%!L%%!) do ( %$\n%
                set ^"$=%%!%%~1:~%%#%%!^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCC^
BBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAA99999999999999998888888888888888^
7777777777777777666666666666666655555555555555554444444444444444^
333333333333333322222222222222221111111111111111^" %$\n%
                set /a L+=0x%%!$:~511,1%%!%%!$:~255,1%%! %$\n%
            ) %$\n%
        ) %$\n%
        for %%# in (%%!L%%!) do ( %$\n%
            endlocal %$\n%
            set %%~2=%%# %$\n%
        ) %$\n%
    ) %$\n%
 ) else setlocal EnableDelayedExpansion ^& set args=

goto :eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:initStrLen
:: Computes the number of bytes in a string.
:: %strLen% str len
::   str - [ByRef In] Name of the variable containing the string to be measured.
::   len - [ByRef Out] Name of the variable that receives the measured length.
:: Strings of up to 8191 characters are supported.
                                                FOR /F %%! IN ("! ^! ^^^!") DO ^
set strLen=for %%. in (1 2) do if %%.==2 (^
  for /f "tokens=1,2" %%1 in ("%%!args%%!") do (^
    set "L=0"^&^
    (if defined %%~1^
      (if "" neq "%%!%%~1:~255%%!"^
        (if "" neq "%%!%%~1:~4095%%!"^
          (set "S=%%!%%~1:~4096%%!"^&set "L=4096") else set "S=%%!%%~1%%!"^
        )^&^
        (if defined S^
          set ^"scale=^
%%!S:~255,1%%!%%!S:~511,1%%!%%!S:~767,1%%!%%!S:~1023,1%%!%%!S:~1279,1%%!^
%%!S:~1535,1%%!%%!S:~1791,1%%!%%!S:~2047,1%%!%%!S:~2303,1%%!%%!S:~2559,1%%!^
%%!S:~2815,1%%!%%!S:~3071,1%%!%%!S:~3327,1%%!%%!S:~3583,1%%!%%!S:~3839,1%%!^
FEDCBA9876543210^"^&^
          set /a "L+=0x%%!scale:~15,1%%!*256"^
        )^
      )^&^
      for %%# in (%%!L%%!) do set ^"S=%%!%%~1:~%%#%%!^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210^
FFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCC^
BBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAA99999999999999998888888888888888^
7777777777777777666666666666666655555555555555554444444444444444^
333333333333333322222222222222221111111111111111^"^&^
      set /a "L+=0x%%!S:~511,1%%!%%!S:~255,1%%!"^
    )^&^
    for %%# in (%%!L%%!) do endlocal^&set "%%~2=%%#"^
  )^
) else setlocal EnableDelayedExpansion^&set args=

goto :eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:initTimediff
for /f %%! in ("! ^! ^^^!") do ^
set timediff=for /l %%# in (1 1 2) do if %%#==2 for /f "tokens=2" %%$ in ("%%!%%! 1 0") do ((if 1==%%$ setlocal EnableDelayedExpansion)^&for /f "tokens=1-3" %%- in ("%%!_i_%%!") do (set "_t1_=%%!%%~-: =0%%!"^&set "_t2_=%%!%%~.: =0%%!"^&^
set /a "_d_=(8640000+(((1%%!_t2_:~,2%%!*60+1%%!_t2_:~3,2%%!)*60+1%%!_t2_:~6,2%%!)*100+1%%!_t2_:~-2%%!-36610100)-(((1%%!_t1_:~,2%%!*60+1%%!_t1_:~3,2%%!)*60+1%%!_t1_:~6,2%%!)*100+1%%!_t1_:~-2%%!-36610100))%%8640000,_o_=100000000+(_d_%%100),_d_/=100,_o_+=(_d_%%60)*100,_d_/=60,_o_+=(_d_%%60)*10000+_d_/60*1000000"^&^
set "_o_=%%!_o_:~1,2%%!:%%!_o_:~3,2%%!:%%!_o_:~5,2%%!.%%!_o_:~-2%%!"^&for /f %%' in ("%%!_o_%%!") do ((if 1==%%$ endlocal)^&if "%%~/"=="" (echo %%') else set "%%~/=%%'"))) else set _i_=
goto :eof

:test
echo(
setlocal EnableDelayedExpansion
for /l %%i in (1 1 4) do (
  set t1=!time!
  for /l %%i in (1 1 1000) do %strLen% %1 len
  set t2=!time!
  echo !len!
  %timediff% t1 t2 diff
  echo !diff!
)
endlocal
goto :eof
... and it's results (the "final combination" block contains the times of the latest macro):

Code: Select all


~~~~~~~~~~~~~~~~~~~~
Steffen

8191
00:00:01.66
8191
00:00:01.54
8191
00:00:01.49
8191
00:00:01.48

1000
00:00:01.02
1000
00:00:01.01
1000
00:00:01.03
1000
00:00:01.03

200
00:00:00.76
200
00:00:00.79
200
00:00:00.79
200
00:00:00.78

10
00:00:00.78
10
00:00:00.77
10
00:00:00.78
10
00:00:00.78

~~~~~~~~~~~~~~~~~~~~
Francesco

8191
00:00:01.40
8191
00:00:01.44
8191
00:00:01.46
8191
00:00:01.43

1000
00:00:01.20
1000
00:00:01.24
1000
00:00:01.25
1000
00:00:01.21

200
00:00:00.92
200
00:00:00.94
200
00:00:00.95
200
00:00:00.94

10
00:00:00.91
10
00:00:00.94
10
00:00:00.92
10
00:00:00.94

~~~~~~~~~~~~~~~~~~~~
jeb

8191
00:00:01.52
8191
00:00:01.54
8191
00:00:01.54
8191
00:00:01.54

1000
00:00:01.26
1000
00:00:01.29
1000
00:00:01.29
1000
00:00:01.30

200
00:00:00.69
200
00:00:00.72
200
00:00:00.73
200
00:00:00.70

10
00:00:00.70
10
00:00:00.71
10
00:00:00.71
10
00:00:00.71

~~~~~~~~~~~~~~~~~~~~
final combination

8191
00:00:01.20
8191
00:00:01.23
8191
00:00:01.27
8191
00:00:01.22

1000
00:00:00.99
1000
00:00:01.00
1000
00:00:01.00
1000
00:00:01.00

200
00:00:00.75
200
00:00:00.76
200
00:00:00.76
200
00:00:00.76

10
00:00:00.76
10
00:00:00.76
10
00:00:00.76
10
00:00:00.76
Drücken Sie eine beliebige Taste . . .
Average of 5 runs (=20 time values each):

Code: Select all

      |Steffen|Francesco|  jeb  | final
------+-------+---------+-------+-------
 8191 | 01.49 |  01.43  | 01.54 | 01.21
 1000 | 01.03 |  01.21  | 01.30 | 01.01
  200 | 00.79 |  00.93  | 00.71 | 00.76
   10 | 00.78 |  00.93  | 00.70 | 00.76
Steffen

Post Reply