bool Stream_File::DoSeek(Signal &sig, long offset, size_t offsetPrev, SeekMode seekMode) { if (_hFile == INVALID_HANDLE_VALUE) return true; if (_map.hFileMappingObject == nullptr) { DWORD dwMoveMethod = (seekMode == SeekSet)? FILE_BEGIN : (seekMode == SeekCur)? FILE_CURRENT : FILE_BEGIN; DWORD dwPtr = ::SetFilePointer(_hFile, offset, nullptr, dwMoveMethod); if (dwPtr == INVALID_SET_FILE_POINTER) { sig.SetError(ERR_IOError, "seek error"); return false; } } else { if (seekMode == SeekSet) { _map.offset = static_cast<size_t>(offset); } else if (seekMode == SeekCur) { if (offset < 0 && _map.offset < static_cast<size_t>(-offset)) { sig.SetError(ERR_IOError, "seek error"); return false; } _map.offset = static_cast<size_t>(_map.offset + offset); } if (_map.offset > _map.bytes) { sig.SetError(ERR_IOError, "seek error"); return false; } } return true; }
bool CheckArray(Signal &sig, GLenum pname, const Array *pArray) { ParamInfoDict::iterator iter = _pParamInfoDict->find(pname); if (iter == _pParamInfoDict->end()) return true; if (pArray->HasShape(iter->second)) return true; sig.SetError(ERR_ValueError, "the array must contain %d elements", iter->second); return false; }
bool Stream_File::DoSeek(Signal &sig, long offset, size_t offsetPrev, SeekMode seekMode) { if (_fp == nullptr) return true; int origin = (seekMode == SeekSet)? SEEK_SET : (seekMode == SeekCur)? SEEK_CUR : SEEK_SET; if (::fseek(_fp, offset, origin) != 0) { sig.SetError(ERR_IOError, "seek error"); return false; } return true; }
size_t Pointer::StreamEx::DoRead(Signal &sig, void *buff, size_t len) { size_t offset = _pPointer->GetOffset(); size_t bytesEntire = _pPointer->GetEntireSize(); if (offset > bytesEntire) { sig.SetError(ERR_OutOfRangeError, "offset is out of range"); return 0; } size_t bytesToCopy = ChooseMin(bytesEntire - offset, len); ::memcpy(buff, _pPointer->GetPointerC(), bytesToCopy); _pPointer->SetOffset(offset + bytesToCopy); return bytesToCopy; }
bool Stream::Seek(Signal &sig, long offset, SeekMode seekMode) { size_t offsetPrev = _offsetCur; if (seekMode == SeekSet) { _offsetCur = static_cast<size_t>(offset); } else if (seekMode == SeekCur) { _offsetCur = _offsetCur + offset; } else if (seekMode == SeekEnd) { _offsetCur = DoGetSize(); if (offset < 0 && _offsetCur < static_cast<size_t>(-offset)) { sig.SetError(ERR_IOError, "seek error"); return false; } } else { // this must not happen because illegal value has to be rejected before. return false; } if (_peek.buff == nullptr) return DoSeek(sig, offset, offsetPrev, seekMode); if (_offsetCur < offsetPrev) { size_t bytesPeeked = _peek.bytes; if (_peek.offsetRead >= offsetPrev - _offsetCur) { _peek.offsetRead -= (offsetPrev - _offsetCur); return true; } delete[] _peek.buff; _peek.buff = nullptr; _peek.bytes = 0; _peek.offsetRead = 0; if (seekMode == SeekSet) return DoSeek(sig, offset, offsetPrev, SeekSet); offset -= static_cast<long>(bytesPeeked); return DoSeek(sig, offset, offsetPrev, SeekCur); } else { if (_peek.offsetRead + _offsetCur - offsetPrev <= _peek.bytes) { _peek.offsetRead += _offsetCur - offsetPrev; return true; } size_t bytesTrail = _peek.bytes - _peek.offsetRead; delete[] _peek.buff; _peek.buff = nullptr; _peek.bytes = 0; _peek.offsetRead = 0; if (seekMode == SeekSet) return DoSeek(sig, offset, offsetPrev, SeekSet); offset -= static_cast<long>(bytesTrail); return DoSeek(sig, offset, offsetPrev, SeekCur); } }
bool Stream_File::Open(Signal &sig, const char *fileName, UInt32 attr) { Close(); _attr |= attr; _fileName = OAL::MakeAbsPathName(OAL::FileSeparator, fileName); DWORD dwDesiredAccess = IsAppend()? GENERIC_WRITE : IsReadable()? GENERIC_READ : IsWritable()? GENERIC_WRITE : GENERIC_READ; DWORD dwShareMode = FILE_SHARE_READ; DWORD dwCreationDisposition = IsAppend()? OPEN_ALWAYS : IsReadable()? OPEN_EXISTING : IsWritable()? CREATE_ALWAYS : OPEN_EXISTING; _hFile = ::CreateFile(OAL::ToNativeString(_fileName.c_str()).c_str(), dwDesiredAccess, dwShareMode, nullptr, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr); if (_hFile == INVALID_HANDLE_VALUE) { sig.SetError(ERR_IOError, "can't open file '%s'", fileName); return false; } if (IsAppend()) { ::SetFilePointer(_hFile, 0, nullptr, FILE_END); } _map.hFileMappingObject = nullptr; _map.buff = nullptr; _map.bytes = 0; _map.offset = 0; _needCloseFlag = true; if (dwDesiredAccess == GENERIC_READ) { _map.hFileMappingObject = ::CreateFileMapping(_hFile, nullptr, PAGE_READONLY, 0, 0, nullptr); if (_map.hFileMappingObject == nullptr) { // it seems to open an empty file return true; } _map.buff = reinterpret_cast<UChar *>( ::MapViewOfFile(_map.hFileMappingObject, FILE_MAP_READ, 0, 0, 0)); _map.bytes = ::GetFileSize(_hFile, nullptr); _map.offset = 0; } return true; }
int Stream::GetChar(Signal &sig) { char chConv = '\0'; Codec::Decoder *pDecoder = GetCodec()->GetDecoder(); if (pDecoder->FollowChar(chConv)) return static_cast<UChar>(chConv); for (;;) { int ch = DoGetChar(sig); if (ch < 0) return ch; Codec::Result rtn = pDecoder->FeedChar(static_cast<char>(ch), chConv); if (rtn == Codec::RESULT_Complete) { break; } else if (rtn == Codec::RESULT_Error) { sig.SetError(ERR_CodecError, "not a valid character of %s", GetCodec()->GetEncoding()); return -1; } } return static_cast<UChar>(chConv); }
String Stream::ReadChar(Signal &sig) { char chConv = '\0'; String str; Codec::Decoder *pDecoder = GetCodec()->GetDecoder(); for (;;) { int ch = DoGetChar(sig); if (ch < 0) break; Codec::Result rtn = pDecoder->FeedChar(static_cast<char>(ch), chConv); if (rtn == Codec::RESULT_Complete) { str += chConv; break; } else if (rtn == Codec::RESULT_Error) { sig.SetError(ERR_CodecError, "not a valid character of %s", GetCodec()->GetEncoding()); return ""; } } while (pDecoder->FollowChar(chConv)) str += chConv; return str; }
bool Stream_File::Open(Signal &sig, const char *fileName, UInt32 attr) { Close(); _attr |= attr; _fileName = OAL::MakeAbsPathName(OAL::FileSeparator, fileName); char modeMod[8]; if (IsAppend()) { modeMod[0] = 'a'; } else if (IsReadable()) { modeMod[0] = 'r'; } else if (IsWritable()) { modeMod[0] = 'w'; } else { modeMod[0] = 'r'; } modeMod[1] = '\0'; _fp = ::fopen(OAL::ToNativeString(_fileName.c_str()).c_str(), modeMod); if (_fp == nullptr) { sig.SetError(ERR_IOError, "can't open file '%s'", fileName); return false; } _needCloseFlag = true; return true; }
void Rational::SetError_DenominatorZero(Signal &sig) { sig.SetError(ERR_ZeroDivisionError, "denominator can't be zero"); }
bool Stream::CheckBwdSeekable(Signal &sig) const { if (IsBwdSeekable()) return true; sig.SetError(ERR_IOError, "stream is not capable of backward seeking"); return false; }
void Formatter::SetError_WrongFormat(Signal &sig) { sig.SetError(ERR_ValueError, "wrong format for formatter"); }
void Iterator::SetError_InfiniteNotAllowed(Signal &sig) { sig.SetError(ERR_IteratorError, "cannot evaluate infinite iterator"); }
void Iterator::SetError_InvalidDataTypeOfElement(Signal &sig) { sig.SetError(ERR_ValueError, "invalid data type of element"); }
//----------------------------------------------------------------------------- // utility functions //----------------------------------------------------------------------------- void SetError_Curl(Signal &sig, CURLcode code) { sig.SetError(ERR_RuntimeError, "%s", ::curl_easy_strerror(code)); }
void Formatter::SetError_NotEnoughArguments(Signal &sig) { sig.SetError(ERR_TypeError, "not enough arguments for formatter"); }
bool Stream::CheckWritable(Signal &sig) const { if (IsWritable()) return true; sig.SetError(ERR_IOError, "stream is not writable"); return false; }
bool Formatter::DoFormat(Signal &sig, const char *format, Source &source) { bool eatNextFlag; const char *formatp = format; Flags flags; enum { STAT_Start, STAT_FlagsPre, STAT_Flags, STAT_FlagsAfterWhite, STAT_PrecisionPre, STAT_Precision, STAT_Padding, } stat = STAT_Start; for (;;) { char ch = *formatp; eatNextFlag = true; if (ch == '\0') { break; } else if (stat == STAT_Start) { if (ch == '%') { stat = STAT_FlagsPre; } else if (ch == '\n') { for (const char *p = _lineSep; *p != '\0'; p++) { if (!PutChar(sig, *p)) return false; } } else { if (!PutChar(sig, ch)) return false; } } else if (stat == STAT_FlagsPre) { if (ch == '%') { if (!PutChar(sig, ch)) return false; stat = STAT_Start; } else { if (source.IsEnd()) { SetError_NotEnoughArguments(sig); break; } // initialize flags flags.upperCaseFlag = false; flags.leftAlignFlag = false; flags.sharpFlag = false; flags.fieldMinWidth = 0; flags.precision = PREC_Default; flags.plusMode = PLUSMODE_None; flags.charPadding = ' '; eatNextFlag = false; stat = STAT_Flags; } } else if (stat == STAT_Flags) { if (ch == '#') { flags.sharpFlag = true; } else if (ch == '0') { if (!flags.leftAlignFlag) { flags.charPadding = '0'; } } else if (ch == '-') { flags.leftAlignFlag = true; flags.charPadding = ' '; } else if (ch == ' ') { if (flags.plusMode == PLUSMODE_None) { flags.plusMode = PLUSMODE_Space; } stat = STAT_FlagsAfterWhite; } else if (ch == '+') { flags.plusMode = PLUSMODE_Plus; } else if (ch == '*') { Value value = source.GetInt(); if (!value.Is_number()) { sig.SetError(ERR_ValueError, "number is expected for * specifier"); break; } flags.fieldMinWidth = static_cast<int>(value.GetNumber()); if (flags.fieldMinWidth < 0) { flags.leftAlignFlag = true; flags.fieldMinWidth = -flags.fieldMinWidth; } if (source.IsEnd()) { SetError_NotEnoughArguments(sig); break; } } else if ('0' < ch && ch <= '9') { eatNextFlag = false; stat = STAT_Padding; } else if (ch == '.') { stat = STAT_PrecisionPre; } else if (ch == 'l') { // just ignore it } else if (ch == 'd' || ch == 'i') { Value value = source.GetInt(); if (!value.GetClass()->Format_d(this, flags, value)) break; stat = STAT_Start; } else if (ch == 'u') { Value value = source.GetInt(); if (!value.GetClass()->Format_u(this, flags, value)) break; stat = STAT_Start; } else if (ch == 'b') { Value value = source.GetInt(); if (!value.GetClass()->Format_b(this, flags, value)) break; stat = STAT_Start; } else if (ch == 'o') { Value value = source.GetInt(); if (!value.GetClass()->Format_o(this, flags, value)) break; stat = STAT_Start; } else if (ch == 'x' || ch == 'X') { Value value = source.GetInt(); flags.upperCaseFlag = (ch == 'X'); if (!value.GetClass()->Format_x(this, flags, value)) break; stat = STAT_Start; } else if (ch == 'e' || ch == 'E') { Value value = source.GetDouble(); flags.upperCaseFlag = (ch == 'E'); if (!value.GetClass()->Format_e(this, flags, value)) break; stat = STAT_Start; } else if (ch == 'f' || ch == 'F') { Value value = source.GetDouble(); if (!value.GetClass()->Format_f(this, flags, value)) break; stat = STAT_Start; } else if (ch == 'g' || ch == 'G') { Value value = source.GetDouble(); flags.upperCaseFlag = (ch == 'G'); if (!value.GetClass()->Format_g(this, flags, value)) break; stat = STAT_Start; } else if (ch == 's') { Value value = source.GetString(); if (!value.GetClass()->Format_s(this, flags, value)) break; stat = STAT_Start; } else if (ch == 'c') { Value value = source.GetInt(); if (!value.GetClass()->Format_c(this, flags, value)) break; stat = STAT_Start; } else { SetError_WrongFormat(sig); break; } } else if (stat == STAT_FlagsAfterWhite) { if (ch == ' ') { SetError_WrongFormat(sig); break; } else { eatNextFlag = false; stat = STAT_Flags; } } else if (stat == STAT_Padding) { if ('0' <= ch && ch <= '9') { flags.fieldMinWidth = flags.fieldMinWidth * 10 + (ch - '0'); } else { eatNextFlag = false; stat = STAT_Flags; } } else if (stat == STAT_PrecisionPre) { if (ch == '*') { Value value = source.GetInt(); if (!value.Is_number()) { sig.SetError(ERR_ValueError, "number is expected for * specifier"); break; } flags.precision = static_cast<int>(value.GetNumber()); if (flags.precision < 0) flags.precision = PREC_Default; if (source.IsEnd()) { SetError_NotEnoughArguments(sig); break; } stat = STAT_Flags; } else if ('0' <= ch && ch <= '9') { flags.precision = 0; eatNextFlag = false; stat = STAT_Precision; } else { flags.precision = PREC_Null; eatNextFlag = false; stat = STAT_Flags; } } else if (stat == STAT_Precision) { if ('0' <= ch && ch <= '9') { flags.precision = flags.precision * 10 + (ch - '0'); } else { eatNextFlag = false; stat = STAT_Flags; } } if (eatNextFlag) formatp++; } return !sig.IsSignalled(); }