cortav  Diff

Differences From Artifact [dec9af930b]:

To Artifact [9b28e1fde4]:


   761    761   			return str
   762    762   		end
   763    763   	};
   764    764   }
   765    765   
   766    766   function ss.classinstance(o)
   767    767   	local g = getmetatable(o)
   768         -	if not o then return nil end
          768  +	if not g then return nil end
   769    769   	local mm = getmetatable(g)
   770         -	if not o then return nil end
          770  +	if not mm then return nil end
   771    771   	if mm.__name == 'class' then
   772    772   		return g
   773    773   	else
   774    774   		return nil
   775    775   	end
   776    776   end
   777    777   
................................................................................
  1214   1214   	if #a ~= #b then return false end
  1215   1215   	eq = eq or function(p,q) return p == q end
  1216   1216   	for i = 1, #a do
  1217   1217   		if not eq(a[i],b[i]) then return false end
  1218   1218   	end
  1219   1219   	return true
  1220   1220   end
         1221  +
         1222  +ss.os = {}
         1223  +function ss.os.getcwd()
         1224  +	return os.getenv 'PWD' -- :((( HAX
         1225  +end
         1226  +
         1227  +ss.path = ss.declare {
         1228  +	ident = 'path';
         1229  +	mk = function() return {
         1230  +		relative = true;
         1231  +		elts = {};
         1232  +	} end;
         1233  +	construct = function(me, o, rel)
         1234  +		if type(o) == 'string' then
         1235  +			if o:sub(1,1) == '/' then
         1236  +				me.relative = false
         1237  +			end
         1238  +			me.elts = ss.str.split(ss.str.enc.ascii, o, '/')
         1239  +		elseif type(o) == 'table' then
         1240  +			me.elts = o
         1241  +			me.relative = rel
         1242  +		end
         1243  +	end;
         1244  +	clonesetup = function(me)
         1245  +		me.elts = ss.clone(me.elts)
         1246  +	end;
         1247  +	cast = {
         1248  +		string = function(me)
         1249  +			return (me.relative and '' or '/') ..
         1250  +				table.concat(me.elts, '/')
         1251  +		end;
         1252  +	};
         1253  +	op = {
         1254  +		sub = function(a,b)
         1255  +			if a.relative ~= b.relative then
         1256  +				return nil
         1257  +			end
         1258  +
         1259  +			local np = ss.path({}, true)
         1260  +			local brk = false
         1261  +			for i=1, math.max(#a.elts,#b.elts) do
         1262  +				if not brk then
         1263  +					if a.elts[i] ~= b.elts[i] then
         1264  +						brk = true
         1265  +					end
         1266  +				end
         1267  +				if brk then
         1268  +					table.insert(np.elts, b.elts[i])
         1269  +				end
         1270  +			end
         1271  +
         1272  +			return np
         1273  +		end;
         1274  +		sum = function(a,b)
         1275  +			if b.relative == false then
         1276  +				return nil
         1277  +			end
         1278  +			local n = a:clone()
         1279  +			local i = #n.elts
         1280  +			for j, v in ipairs(b.elts) do
         1281  +				n.elts[i+j] = v
         1282  +			end
         1283  +			return n
         1284  +		end;
         1285  +		lt = function(a,b)
         1286  +			-- '/a/b/c' < '/a/b/c/d'
         1287  +			-- 'q/f/g' < 'q/f/g/p/d'
         1288  +			-- '/a' !< '/b', '/a' !< 'a'
         1289  +			if a.relative ~= b.relative then
         1290  +				return false
         1291  +			end
         1292  +			if #a.elts > #b.elts then return false end
         1293  +			for i=1, #a.elts do
         1294  +				if a.elts[i] ~= b.elts[i] then
         1295  +					return false
         1296  +				end
         1297  +			end
         1298  +			return true
         1299  +		end;
         1300  +	};
         1301  +	fns = {
         1302  +		dir = function(me)
         1303  +			local n = ss.copy(me.elts)
         1304  +			n[#n] = nil
         1305  +			local p = ss.path(n, me.relative)
         1306  +		end;
         1307  +		normalize = function(me)
         1308  +			local np = ss.path({}, me.relative)
         1309  +			for i, e in ipairs(me.elts) do
         1310  +				if e == '..' then
         1311  +					if me.relative and (
         1312  +						next(np.elts) == nil or
         1313  +						np.elts[#np.elts] == '..'
         1314  +					) then
         1315  +						table.insert(np.elts, '..')
         1316  +					else
         1317  +						table.remove(np.elts)
         1318  +					end
         1319  +				elseif e ~= '.' then
         1320  +					table.insert(np.elts, e)
         1321  +				end
         1322  +			end
         1323  +			return np
         1324  +		end
         1325  +	};
         1326  +	cfns = {
         1327  +		cwd = function()
         1328  +			return ss.path(ss.os.getcwd())
         1329  +		end;
         1330  +	};
         1331  +}
  1221   1332   
  1222   1333   ss.uri = ss.declare {
  1223   1334   	ident = 'uri';
  1224   1335   	mk = function() return {
  1225   1336   		class = nil;
  1226   1337   		namespace = nil;
  1227   1338   		path = nil;
................................................................................
  1242   1353   			local s,r = rem:match '^([^:]+):(.*)$'
  1243   1354   			s_class, rem = s,r
  1244   1355   		end
  1245   1356   		if not rem then
  1246   1357   			ss.uri.exn('invalid URI ā€œ%sā€', str):throw()
  1247   1358   		end
  1248   1359   		local s_ns do
  1249         -			local s,r = rem:match '^//([^/]*)(.*)$'
         1360  +			local s,r = rem:match '^//([^/?#]*)(.*)$'
  1250   1361   			if s then s_ns, rem = s,r end
  1251   1362   		end
  1252   1363   		local h_query
  1253   1364   		local s_frag
  1254   1365   		local s_path if rem ~= '' then
  1255   1366   			local s,q,r = rem:match '^([^?#]*)([?#]?)(.*)$'
  1256   1367   			if s == '' then s = nil end
................................................................................
  1303   1414   		me.namespace = dec(s_ns)
  1304   1415   		me.path = dec(s_path)
  1305   1416   		me.query = dec(s_query)
  1306   1417   		me.frag = dec(s_frag)
  1307   1418   	end;
  1308   1419   	cast = {
  1309   1420   		string = function(me)
         1421  +			return me:construct('class','namespace','path','query','frag')
         1422  +		end;
         1423  +	};
         1424  +	fns = {
         1425  +		canfetch = function(me)
         1426  +			for id, pr in pairs(fetchableProtocols) do
         1427  +				for _, p in ipairs(pr.proto) do
         1428  +					if ss.match(me.class, p) then return id end
         1429  +				end
         1430  +			end
         1431  +			return false
         1432  +		end;
         1433  +		construct = function(me, ...)
         1434  +			local parts = {}
         1435  +			local function add(n, ...)
         1436  +				if n == nil then return end
         1437  +				table.insert(parts, me:part(n))
         1438  +				add(...)
         1439  +			end
         1440  +			add(...)
         1441  +			return table.concat(parts)
         1442  +		end;
         1443  +		part = function(me, p)
  1310   1444   			local function san(str, chars)
  1311   1445   				-- TODO IRI support
  1312   1446   				chars = chars or ''
  1313   1447   				local ptn = '-a-zA-Z0-9_.,;'
  1314   1448   				ptn = ptn .. chars
  1315   1449   				return (str:gsub('[^'..ptn..']', function(c)
  1316   1450   					if c == ' ' then return '+' end
  1317   1451   					return string.format('%%%02X', string.byte(c))
  1318   1452   				end))
  1319   1453   			end
  1320         -			if me.class == nil or next(me.class) == nil then
  1321         -				return 'none:'
  1322         -			end
  1323         -			local parts = {
  1324         -				table.concat(ss.map(san,me.class), '+') .. ':';
  1325         -			}
  1326         -			if me.namespace or me.auth or me.svc then
  1327         -				table.insert(parts, '//')
  1328         -				if me.auth then
  1329         -					table.insert(parts, san(me.auth,':') .. '@')
         1454  +			if p == 'class' then
         1455  +				if me.class == nil or next(me.class) == nil then
         1456  +					return 'none:'
  1330   1457   				end
  1331         -				if me.namespace then
  1332         -					table.insert(parts, san(me.namespace))
  1333         -				end
  1334         -				if me.svc then
  1335         -					table.insert(parts, ':' .. san(me.svc))
  1336         -				end
  1337         -				if me.path and not ss.str.begins(me.path, '/') then
  1338         -					table.insert(parts, '/')
         1458  +				return table.concat(ss.map(san,me.class), '+') .. ':';
         1459  +			else
         1460  +				if me[p] == nil then return '' end
         1461  +				if p == 'namespace' then
         1462  +					local parts = {}
         1463  +					if me.namespace or me.auth or me.svc then
         1464  +						table.insert(parts, '//')
         1465  +						if me.auth then
         1466  +							table.insert(parts, san(me.auth,':') .. '@')
         1467  +						end
         1468  +						if me.namespace then
         1469  +							table.insert(parts, san(me.namespace))
         1470  +						end
         1471  +						if me.svc then
         1472  +							table.insert(parts, ':' .. san(me.svc))
         1473  +						end
         1474  +						if me.path and not ss.str.begins(me.path, '/') then
         1475  +							table.insert(parts, '/')
         1476  +						end
         1477  +					end
         1478  +					return table.concat(parts)
         1479  +				elseif p == 'path' then
         1480  +					return san(me.path,'+/=&')
         1481  +				elseif p == 'query' then
         1482  +					return '?' .. san(me.query,'?+/=&')
         1483  +				elseif p == 'frag' then
         1484  +					return '#' .. san(me.frag,'+/=&')
  1339   1485   				end
  1340   1486   			end
  1341         -			if me.path then
  1342         -				table.insert(parts, san(me.path,'+/=&'))
  1343         -			end
  1344         -			if me.query then
  1345         -				table.insert(parts, '?' .. san(me.query,'?+/=&'))
  1346         -			end
  1347         -			if me.frag then
  1348         -				table.insert(parts, '#' .. san(me.frag,'+/=&'))
  1349         -			end
  1350         -			return table.concat(parts)
  1351         -		end;
  1352         -	};
  1353         -	fns = {
  1354         -		canfetch = function(me)
  1355         -			for id, pr in pairs(fetchableProtocols) do
  1356         -				for _, p in ipairs(pr.proto) do
  1357         -					if ss.match(me.class, p) then return id end
  1358         -				end
  1359         -			end
  1360         -			return false
  1361   1487   		end;
  1362   1488   		fetch = function(me, env)
  1363   1489   			local pid = me:canfetch()
  1364   1490   			if (not pid) or fetchableProtocols[pid].fetch == nil then
  1365   1491   				ss.uri.exn("URI ā€œ%sā€ is unfetchable", tostring(me)):throw()
  1366   1492   			end
  1367   1493   			local proto = fetchableProtocols[pid]