Страница 1 из 1

Очередной баг Клаши

Добавлено: 09 Ноябрь 2016, 14:47
PavelNK
При написании очень часто использую функции Match и StrPos. Это очень удобно при поиске и разборе текстовой информации.
Написал очередную функцию, стал проверять - чертовщина какая-то! Частично работает, а частично - нет. Т.е. некоторые тексты разбирает нормально, некоторые наполовину, до определенного места разбирает, а дальше ни в какую. Стал разбирать, полдня убил.
Оказалось, что функция StrPos прекрасно ищет подстроку в строке, но только если искомая подстрока находится не дальше от начала строки чем 64К. Если дальше, то ничего не находит, хотя искомые строки есть. У меня установлена версия 10, релиз 12258.
Будьте осторожны!
Если кто-то общается с велосипедистами, то убедительная просьба, напишите им - может поправят!

Очередной баг Клаши

Добавлено: 09 Ноябрь 2016, 16:19
kreator
PavelNK, а попробуйте для примера функцию instring(). Не совсем то, но у instring для параметра явно написано "A string constant, or the label of the STRING, CSTRING, or PSTRING variable to be searched". А для strpos и match не указано, строго говоря. Что они понимают под "A string containing data to compare against the second parameter"?

Очередной баг Клаши

Добавлено: 09 Ноябрь 2016, 18:30
Игорь Столяров
Это не единственная "особенность" встроенных функций поиска ...
Обратите внимание на интересный нюанс. Если посмотреть какой-нибудь код SV работы с текстом,
где есть поиск и замена в строках неизвестной длины (например JSON.CLW) - они нигде не используют
StrPos() и Instring(). Все делают банальным перебором строки по символам, по всей длине строки.
Интересно, почему ? ;)

Очередной баг Клаши

Добавлено: 09 Ноябрь 2016, 20:59
PavelNK
Я естественно часто использую instring, но когда поиск сложный, то хочется сделать проще, понятней, наглядней, а не изобретать сложных конструкций анализа строки используя примитивные функции. Что касается перебора символов, то практика показывает, что это очень медленный способ, причем он существенно медленнее, чем поиск instring. То что наваяли в JSON.CLW - это вообще тихий ужас. Попытка применения для разбора JSON показала, что библиотека содержит кучу ошибок. И в целом ряде случаев не выдает результат или выдает неправильный результат.

Очередной баг Клаши

Добавлено: 09 Ноябрь 2016, 21:36
Игорь Столяров
PavelNK писал(а): То что наваяли в JSON.CLW - это вообще тихий ужас.
Согласен, но JSON еще допиливают, да и вообще все в открытом тексте - можно дописывать в меру потребностей и способностей. :)

Здесь наверно должно быть понимание, что методы работы со строками и массивами текстовой информации - разные.
Видимо ограничение в 64K - это двухбайтовая адресация страницы памяти для функций WinAPI, на которых построена
обработка строк ...

Очередной баг Клаши

Добавлено: 09 Ноябрь 2016, 22:36
Yufil
А что такое перебор символов? Если подстрока берётся по Instring, происходит копирование двух параметров на строковый стек. Если строки большие, может быть, весьма тормозная операция. Всё-таки пробежаться по строке, используя вырезку, или, возможно, адресную арифметику и сишные функции, побыстрее будет

Очередной баг Клаши

Добавлено: 10 Ноябрь 2016, 7:32
Игорь Столяров
Yufil писал(а): или, возможно, адресную арифметику и сишные функции, побыстрее будет
Точно ! Вспомнил, этот вопрос обсуждался и кто-то публиковал поиск текста на API (простите, не помню кто именно).
Примерно вот так делаем упрощенный аналог InString() - без управления начала поиска и шага (всегда 1):

Код: Выделить всё

  Module ('')  ! В Global MAP
    ToUpper(byte char), byte, name('Cla$isftoupper')     ! ToUpper is far more efficient for single character conversion
    MemCmp(ulong buf1, ulong buf2, unsigned count), long, name('_memcmp')     ! GCR
    MemChr(ulong buf, long c, unsigned count), long, name('_memchr')          ! GCR
  end

FFind                PROCEDURE  (pSearchValue,p_Text)

trLen      long, auto
SearchLen   long, auto
i           long, auto
CharVal     long, auto
endAddress  long, auto
Addr        long, auto

  CODE
  
  StrLen = Len(p_text)
  Addr   = Address(p_Text)

  SearchLen = Size(pSearchValue)
  If StrLen = 0 Or SearchLen = 0 Or strLen < SearchLen  ! строка для поиска меньше, чем искомое значение
     Return 0
  end

  CharVal    = Val(pSearchValue[1])
  EndAddress = Addr + strLen - SearchLen
  i          = Addr          ! Установить начальный адрес для поиска

  Loop
    i = memchr(i, CharVal, EndAddress - i + 1)  ! Адрес первого символа pSearchValue
    If i = 0 then Return 0.                     ! Первый символ не найден

    ! у нас матч на первый символ содержит адреса - теперь проверка на совпадение в целом строке поиска
    if memcmp(i, Address(pSearchValue), searchLen) = 0 ! Найдено ? (with memcmp 0 = match)
       Return(i - Addr + 1)                             ! вернуть позицию байта, где pSearchValue совпало
    end

    If i < EndAddress
       i += 1                             ! не матч так адрес начала инкремент I и попробовать снова
    else
       Return 0                           ! pSearchValue не найдена
    end
  end

Очередной баг Клаши

Добавлено: 10 Ноябрь 2016, 12:34
PavelNK
Игорь Столяров писал(а): Согласен, но JSON еще допиливают, да и вообще все в открытом тексте - можно дописывать в меру потребностей и способностей.
Я понимаю, если бы это было что-то новое, но это уже существует уже не один год, во многих языках существуют подобные библиотеки, причем с гораздо более широкими возможностями и работающие без ошибок! А у нас как всегда допиливают, а что не допилили можно допилить, дописать, исправить самому.
Yufil писал(а): Если строки большие, может быть, весьма тормозная операция.
Естественно, но своя писанина будет не быстрее работать, чем хорошо написанные, отлаженные функции. Конечно, можно пытаться как-то ускорить процесс, в основном это возможно когда уже есть какая-то инфа о тексте, но если нужно найти подстроку в тексте о котором нет информации, то как не изгаляйся процесс всегда сводится к банальному "пробежаться по тексту". Как правило подобные библиотеки пишут очень хорошие грамотные программисты, одной из задач которых является достичь максимальной скорости работы функции. Поэтому написать самому лучше вряд-ли получиться.
Игорь Столяров писал(а): Точно ! Вспомнил, этот вопрос обсуждался и кто-то публиковал поиск текста на API (простите, не помню кто именно).
Примерно вот так делаем упрощенный аналог InString() - без управления начала поиска и шага (всегда 1):
Кстати о функции, проверил - она работает процентов на 15 медленнее INSTRING!

Очередной баг Клаши

Добавлено: 10 Ноябрь 2016, 14:54
kreator
PavelNK писал(а):Кстати о функции, проверил - она работает процентов на 15 медленнее INSTRING!
Я бы тоже не стал так уж обс...ть программистов SV. Нормально работающие функции. Было дело, проверял запись большого текстового файла. Драйвер ASCII работает также как и Винапишные функции.

Очередной баг Клаши

Добавлено: 10 Ноябрь 2016, 15:14
PavelNK
kreator писал(а): Я бы тоже не стал так уж обс...ть программистов SV. Нормально работающие функции. Было дело, проверял запись большого текстового файла. Драйвер ASCII работает также как и Винапишные функции.
Проверено! Не также! Еще несколько лет назад ставил эксперимент, читал один и тот же файл много раз, варианты
1. Клаша, драйвер ASCII
2. Клаша, драйвер DOS
3. WinAPI

Результаты, сильно отличаются. WinAPI сильно выигрывает, а ASCII вообще тормоз.

Очередной баг Клаши

Добавлено: 10 Ноябрь 2016, 15:20
PavelNK
kreator писал(а): Я бы тоже не стал так уж обс...ть программистов SV. Нормально работающие функции. Было дело, проверял запись большого текстового файла. Драйвер ASCII работает также как и Винапишные функции.
В части INSTRING я и не об..рал, а наоборот, хвалил - она работает быстрее самопала

Очередной баг Клаши

Добавлено: 11 Ноябрь 2016, 9:57
Игорь Столяров
PavelNK писал(а): В части INSTRING я и не об..рал, а наоборот, хвалил - она работает быстрее самопала
Про скорость-то понятно и ожидаемо ... здесь вопрос в том, удалось ли с ее помощью искать в строках больше 64K ?
PavelNK писал(а): Результаты, сильно отличаются. WinAPI сильно выигрывает, а ASCII вообще тормоз.
Согласен, если порыться в форуме - я несколько лет назад этот вопрос поднимал.
Пытались выгружать большие массивы данных через ABXML (сделан через драйвер ASCII) - это что-то страшное ....
Ну как большие ... Тысяч 100 записей о товарах по 20-30 полей каждая запись. Ничего военного вроде бы, но оно выгружалось
несколько часов. Причем видно, что скорость записи сильно падает по ходу нарастания размера файла.
Переделали на DOS драйвер с /FILEBUFFERS=65536' - та же самая выгрузка 1-2 минуты ...

Очередной баг Клаши

Добавлено: 11 Ноябрь 2016, 12:19
kreator
Игорь Столяров писал(а):Пытались выгружать большие массивы данных через ABXML (сделан через драйвер ASCII) - это что-то страшное ....
Ну как большие ... Тысяч 100 записей о товарах по 20-30 полей каждая запись. Ничего военного вроде бы, но оно выгружалось
несколько часов.
Я тоже выгружаю в xml через ASCII драйвер. Проверил. ~16000 записей (запись - 2000 символов) выгружаются меньше секунды. Не показатель, маловато записей. В голове буду держать, если столкнусь с большими объёмами, проверю.
Но это сейчас так, а не несколько лет назад. Может и в этом дело.