﻿id	summary	reporter	owner	description	type	status	priority	milestone	component	version	resolution	keywords	cc
23943	"Mapcss ""substring"" function: allow negative end index to remove from the end"	Famlam	team	"**The problem**
Recently I had to [https://github.com/osm-fr/osmose-backend/blob/8bf8f8bdfb2276a72aa760844879f7d90500070a/plugins/TagFix_MultipleTag2.validator.mapcss#L225 use] the following mapcss line:
{{{#!mapcss
fixAdd: concat(""alt_name="", join_list("";"", trim_list(split("";"", replace(concat("";"", join_list("";"", trim_list(split("";"", tag(""alt_name"")))), "";""), concat("";"", tag(""name""), "";""), "";"")))));
}}}

This consists of three parts:
1. the outer `concat` to just merge key and value (this is fine)
2. the inner `replace(...)` which effectively removes the value of `name` from a `;`-separated value of `alt_name` (this is fine)
3. the in-between part `join_list("";"", trim_list(split("";"", ...)))` which effectively only serves to remove the `;` at the start and end of the string.

Part 3 is obviously not elegant. Although there are other theoretical solutions, e.g.:
- `get(regexp_match(""^;(.+);$"", ...), 1)`
- `substring(..., 1, length(...)-1)`

where `...` should be replaced by the part under number 2 (the `replace(...)`), they're obviously not the most elegant solutions either (especially the second which needs the lengthy `replace(...)`-part twice.

**Proposed feature**
A much nicer solution would be to permit negative end indices in the `substring(str, start, end)` function, which should mean to count the final index from the length of the string, e.g.: `substring(""foo bar baz"", 1, -1)` would return `oo bar ba`. This is especially useful for variable-length strings in mapcss.

I'm not familiar enough with Java to dare to make it a patch, but I can image the new function to look something like:
{{{#!java
public static String substring(String s, float begin, float end) {
  return s == null ? null : s.substring((int) begin, (int) (end > 0 ? end : s.length() + end));
}
}}}
(Possibly with a safeguard that `start <= (end > 0 ? end : s.length() + end)`, but this safeguard currently also doesn't exist for the positive-indices-only implementation)
Current code: [https://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Functions.java#L1041 here]


----

On a side note, the current behavior is that JOSM crashes with `java.lang.StringIndexOutOfBoundsException: Range [1, -1) out of bounds for length X` when you use a negative end index (or when the start index is larger than the end index).



----

{{{
Revision:19207
Build-Date:2024-09-03 10:31:55
}}}
"	enhancement	new	normal		Core validator			mapcss substring	
